[RK3288-Android8.1]cw2015驱动调试曲折

Android8.1使用的是kernel4.4,驱动中自带的cw2015没有dc_det功能,因此需要将之前Android6.0,kernel3.1中使用的cw2015驱动尝试移植到8.1中。

代码拷贝过来后果然很多报错。编译过程中,包括rk_bat,rk_ac,rk_usb均会报错power_supply 没有成员 type,properties等

 

static int cw_bat_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
中,cw_bat->rk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
	cw_bat->rk_bat.properties = rk_battery_properties;
	cw_bat->rk_bat.num_properties = ARRAY_SIZE(rk_battery_properties);
	cw_bat->rk_bat.get_property = rk_battery_get_property;
	ret = power_supply_register(&client->dev, &cw_bat->rk_bat);

很显然是内核的接口变了, 查看include/linux/power_supply.h中struct power_supply的定义:

struct power_supply {
	const struct power_supply_desc *desc;

	char **supplied_to;
	size_t num_supplicants;

	char **supplied_from;
	size_t num_supplies;
	struct device_node *of_node;

	/* Driver private data */
	void *drv_data;

	/* private */
	struct device dev;
	struct work_struct changed_work;
	struct delayed_work deferred_register_work;
	spinlock_t changed_lock;
	bool changed;
	bool initialized;
	atomic_t use_cnt;
#ifdef CONFIG_THERMAL
	struct thermal_zone_device *tzd;
	struct thermal_cooling_device *tcd;
#endif

#ifdef CONFIG_LEDS_TRIGGERS
	struct led_trigger *charging_full_trig;
	char *charging_full_trig_name;
	struct led_trigger *charging_trig;
	char *charging_trig_name;
	struct led_trigger *full_trig;
	char *full_trig_name;
	struct led_trigger *online_trig;
	char *online_trig_name;
	struct led_trigger *charging_blink_full_solid_trig;
	char *charging_blink_full_solid_trig_name;
#endif
};

的确是没有这些成员了,不过看一眼便知,这些成员都封装在power_supply_desc 这个结构体中:

struct power_supply_desc {
	const char *name;
	enum power_supply_type type;
	enum power_supply_property *properties;
	size_t num_properties;

	/*
	 * Functions for drivers implementing power supply class.
	 * These shouldn't be called directly by other drivers for accessing
	 * this power supply. Instead use power_supply_*() functions (for
	 * example power_supply_get_property()).
	 */
	int (*get_property)(struct power_supply *psy,
			    enum power_supply_property psp,
			    union power_supply_propval *val);
	int (*set_property)(struct power_supply *psy,
			    enum power_supply_property psp,
			    const union power_supply_propval *val);
	/*
	 * property_is_writeable() will be called during registration
	 * of power supply. If this happens during device probe then it must
	 * not access internal data of device (because probe did not end).
	 */
	int (*property_is_writeable)(struct power_supply *psy,
				     enum power_supply_property psp);
	void (*external_power_changed)(struct power_supply *psy);
	void (*set_charged)(struct power_supply *psy);

	/*
	 * Set if thermal zone should not be created for this power supply.
	 * For example for virtual supplies forwarding calls to actual
	 * sensors or other supplies.
	 */
	bool no_thermal;
	/* For APM emulation, think legacy userspace. */
	int use_for_apm;
};

如此来看,只需要在代码中多加一个指向成员就可以了吗?然而这个desc在power_supply中是const的,如此修改编译器只会告诉你desc是只读的,不允许定义后修改,那么只剩下一种方案了,就是在power_supply初始化之后,
定义一个power_supply_desc指针,将需要初始化的内容填充好,然后把这个指针传给power_supply中的desc。这种方法还有两种方案,一种是在初始化的过程中动态的去申请和传递,另一种是在初始化之前,直接静态定义好
接口,初始化之后直接传递,后者写起来比较方便,但是直接定义静态的const数据不太好,还是动态申请吧:

struct power_supply_desc *rk_bat_desc;
rk_bat_desc = devm_kzalloc(&client->dev, sizeof(*rk_bat_desc), GFP_KERNEL);
	if (!rk_bat_desc)
		return -ENOMEM;
	
	rk_bat_desc->name = "rk-bat";
	rk_bat_desc->type = POWER_SUPPLY_TYPE_BATTERY;
	rk_bat_desc->properties = rk_battery_properties;
	rk_bat_desc->num_properties = ARRAY_SIZE(rk_battery_properties);
	rk_bat_desc->get_property = rk_battery_get_property;

其中,注册的接口也变化了:

extern struct power_supply *__must_check
power_supply_register(struct device *parent,
				 const struct power_supply_desc *desc,
				 const struct power_supply_config *cfg);

第二个参数接受的是 power_supply_desc, 第三个这是power_supply_config,所以还需要构建一个cfg指针,cfg需要接受一个device作为 drv_data,

struct power_supply_config psy_cfg = { .drv_data = cw_bat, };

同时返回一个 struct power_supply, 旧接口返回的是一个int错误码,可以判断是否注册成功,新的接口可以把返回值赋给cw_bat->rk_bat:

cw_bat->rk_bat = power_supply_register(&client->dev, rk_bat_desc, &psy_cfg);

后,在这个函数中,还会报错: get_gadget_connect_flag()未定义,也是新内核中usb的接口变化了,搜一下代码发现这个方法只用于初始化一个值,直接替换成0即可。

static int get_usb_charge_state(struct cw_battery *cw_bat)
{
	int charge_time;
	int time_from_boot;
	struct timespec ts;

	int gadget_status = get_gadget_connect_flag();
	int usb_status = dwc_vbus_status();

	get_monotonic_boottime(&ts);
	time_from_boot = ts.tv_sec;

	if (cw_bat->charger_init_mode) {
		if (usb_status == 1 || usb_status == 2) {
			cw_bat->charger_init_mode = 0;
		} else if (time_from_boot < 8) {
			usb_status = cw_bat->charger_init_mode;
		} else if (strstr(saved_command_line, "charger")) {
			cw_bat->charger_init_mode = dwc_otg_check_dpdm();
			usb_status = cw_bat->charger_init_mode;
		}
	}
#ifdef NO_STANDARD_AC_BIG_CHARGE_MODE
	if (cw_bat->usb_online == 1) {
		charge_time =
		    time_from_boot - cw_bat->sleep_time_charge_start -
		    cw_bat->run_time_charge_start;
		if (charge_time > 3) {
			if (gadget_status == 0 && dwc_vbus_status() == 1)
				usb_status = 2;
		}
	}
#endif

	dev_dbg(&cw_bat->client->dev,
		"%s usb_status=[%d],cw_bat->charger_mode=[%d],cw_bat->gadget_status=[%d], cw_bat->charger_init_mode = [%d]\n",
		__func__, usb_status, cw_bat->charger_mode, gadget_status,
		cw_bat->charger_init_mode);

	return usb_status;
}

再次编译,成功通过。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一份针对RK3288-EVB-Android SDK的DTS文件修改示例,可以实现SD卡启动: ``` /dts-v1/; /plugin/; / { model = "Rockchip RK3288-EVB board"; compatible = "rockchip,rk3288-evb"; memory@60000000 { device_type = "memory"; reg = <0x60000000 0x40000000>; }; chosen { bootargs = "console=ttyS2,115200n8 root=/dev/mmcblk1p2 rw rootwait earlyprintk"; stdout-path = &uart2; }; uart2: serial@11004000 { compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart"; reg = <0x11004000 0x1000>; interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>; clocks = <&uart2_clk>; clock-names = "uartclk"; status = "okay"; }; sdhci@11014000 { compatible = "rockchip,rk3288-dw-mshc"; reg = <0x11014000 0x1000>; interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>; clocks = <&cru SCLK_SDMMC>, <&cru PCLK_SDMMC>; clock-names = "sdmmc", "apb_pclk"; pinctrl-names = "default"; pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4 &sdmmc_bus8 &sdmmc_cd_n>; status = "okay"; mmc-slot@0 { reg = <0>; bus-width = <8>; cd-gpios = <&gpio7 3 GPIO_ACTIVE_LOW>; non-removable; status = "okay"; }; }; &dpu { status = "okay"; }; &lcdc { status = "okay"; }; &backlight { status = "okay"; }; &act8846_reg { status = "okay"; }; &i2c1 { status = "okay"; act8846: act8846@5b { compatible = "active-semi,act8846"; reg = <0x5b>; gpio-controller; #gpio-cells = <2>; interrupt-parent = <&gpio2>; interrupts = <6 IRQ_TYPE_LEVEL_LOW>; status = "okay"; }; }; &mmc { status = "okay"; }; &mmc1 { status = "okay"; }; &mmc2 { status = "okay"; }; &mmc3 { status = "okay"; }; &mmc4 { status = "okay"; }; &sdmmc_clk { rockchip,pins = <RK_GPIO3 8 RK_FUNC_2 &pcfg_pull_none>; }; &sdmmc_cmd { rockchip,pins = <RK_GPIO3 9 RK_FUNC_2 &pcfg_pull_none>; }; &sdmmc_bus4 { rockchip,pins = <RK_GPIO3 10 RK_FUNC_2 &pcfg_pull_none>; }; &sdmmc_bus8 { rockchip,pins = <RK_GPIO3 11 RK_FUNC_2 &pcfg_pull_none>; }; &sdmmc_cd_n { rockchip,pins = <RK_GPIO7 3 RK_FUNC_GPIO &pcfg_pull_up>; }; }; ``` 此外,你还需要在编译内核时加入SD卡启动相关的配置选项。具体方法可以参考RK3288-Android SDK的文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值