Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff -ruN a/4.1.B.0.431//external/webkit/Source/WebCore/rendering/RenderImage.cpp b/4.1.B.0.479//external/webkit/Source/WebCore/rendering/RenderImage.cpp
- --- a/4.1.B.0.431//external/webkit/Source/WebCore/rendering/RenderImage.cpp 2012-05-25 19:07:01.000000000 +0900
- +++ b/4.1.B.0.479//external/webkit/Source/WebCore/rendering/RenderImage.cpp 2012-06-25 19:47:11.000000000 +0900
- @@ -8,6 +8,7 @@
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Portions created by Sony Ericsson are Copyright (C) 2011 Sony Ericsson Mobile Communications AB.
- + * Copyright (C) 2012 Sony Mobile Communications AB.
- * All Rights Reserved.
- *
- * This library is free software; you can redistribute it and/or
- @@ -572,17 +573,32 @@
- #endif
- }
- +/**
- + * A version of RenderBox::computeReplacedLogicalHeight that ignores
- + * a percentage height when there is no specified height on the containing block.
- + */
- +int RenderImage::renderBoxComputeReplacedLogicalHeight() const
- +{
- + int logicalHeight = isLogicalHeightSpecified() ?
- + RenderBox::computeReplacedLogicalHeightUsing(style()->logicalHeight()) :
- + intrinsicLogicalHeight();
- + int minLogicalHeight =
- + RenderBox::computeReplacedLogicalHeightUsing(style()->logicalMinHeight());
- + int maxLogicalHeight = style()->logicalMaxHeight().isUndefined() ? logicalHeight :
- + RenderBox::computeReplacedLogicalHeightUsing(style()->logicalMaxHeight());
- +
- + return max(minLogicalHeight, min(logicalHeight, maxLogicalHeight));
- +}
- +
- int RenderImage::calcAspectRatioLogicalWidth() const
- {
- int intrinsicWidth = intrinsicLogicalWidth();
- int intrinsicHeight = intrinsicLogicalHeight();
- if (!intrinsicHeight)
- return 0;
- - // [SonyEricsson]: Do not scale if no height is specified.
- - if (!m_imageResource->hasImage() || m_imageResource->errorOccurred() ||
- - !isLogicalHeightSpecified())
- + if (!m_imageResource->hasImage() || m_imageResource->errorOccurred())
- return intrinsicWidth; // Don't bother scaling.
- - return RenderBox::computeReplacedLogicalHeight() * intrinsicWidth / intrinsicHeight;
- + return renderBoxComputeReplacedLogicalHeight() * intrinsicWidth / intrinsicHeight;
- }
- int RenderImage::calcAspectRatioLogicalHeight() const
- diff -ruN a/4.1.B.0.431//external/webkit/Source/WebCore/rendering/RenderImage.h b/4.1.B.0.479//external/webkit/Source/WebCore/rendering/RenderImage.h
- --- a/4.1.B.0.431//external/webkit/Source/WebCore/rendering/RenderImage.h 2012-05-25 19:07:01.000000000 +0900
- +++ b/4.1.B.0.479//external/webkit/Source/WebCore/rendering/RenderImage.h 2012-06-25 19:47:11.000000000 +0900
- @@ -4,6 +4,7 @@
- * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
- + * Copyright (C) 2012 Sony Mobile Communications AB.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- @@ -85,6 +86,7 @@
- virtual int computeReplacedLogicalWidth(bool includeMaxWidth = true) const;
- virtual int computeReplacedLogicalHeight() const;
- + int renderBoxComputeReplacedLogicalHeight() const;
- IntSize imageSizeForError(CachedImage*) const;
- void imageDimensionsChanged(bool imageSizeChanged, const IntRect* = 0);
- diff -ruN a/4.1.B.0.431//kernel/arch/arm/mach-msm/board-semc_zeus.c b/4.1.B.0.479//kernel/arch/arm/mach-msm/board-semc_zeus.c
- --- a/4.1.B.0.431//kernel/arch/arm/mach-msm/board-semc_zeus.c 2012-06-10 23:35:47.000000000 +0900
- +++ b/4.1.B.0.479//kernel/arch/arm/mach-msm/board-semc_zeus.c 2012-06-25 19:47:11.000000000 +0900
- @@ -1132,6 +1132,12 @@
- .cdrom_vendor = "SEMC",
- .cdrom_product = "CD-ROM",
- .cdrom_release = 0x0100,
- +
- + /* EUI-64 based identifier format */
- + .eui64_id = {
- + .ieee_company_id = {0x00, 0x0A, 0xD9},
- + .vendor_specific_ext_field = {0x00, 0x00, 0x00, 0x00, 0x00},
- + },
- };
- static struct platform_device mass_storage_device = {
- diff -ruN a/4.1.B.0.431//kernel/drivers/input/touchscreen/cy8ctma300_spi.c b/4.1.B.0.479//kernel/drivers/input/touchscreen/cy8ctma300_spi.c
- --- a/4.1.B.0.431//kernel/drivers/input/touchscreen/cy8ctma300_spi.c 2012-05-25 19:07:09.000000000 +0900
- +++ b/4.1.B.0.479//kernel/drivers/input/touchscreen/cy8ctma300_spi.c 2012-06-25 19:47:11.000000000 +0900
- @@ -823,12 +823,6 @@
- memset(&tp->track_detect[0], TP_FNGR_NOTRACK,
- ARRAY_SIZE(tp->track_detect));
- - if (fdetect) {
- - input_report_key(tp->input, BTN_TOUCH, 1);
- - } else {
- - input_report_key(tp->input, BTN_TOUCH, 0);
- - }
- -
- for (i = 0; i < TP_TOUCH_CNT_MAX; i++) {
- if (tp->track_state[i] == TP_TRACK_ACTIVE)
- cy8ctma300_update_track(tp, i, cur_touch, fdetect);
- @@ -840,9 +834,13 @@
- touch_major = 0;
- pressure = 0;
- tp->track_state[i] = TP_TRACK_INACTIVE;
- - report = 1;
- + report = 0;
- dev_dbg(&tp->spi->dev, "%s: MT report removed "
- "finger\n", __func__);
- +
- + if (!fdetect) {
- + input_mt_sync(tp->input);
- + }
- } else if (tp->track_state[i] == TP_TRACK_ACTIVE) {
- width_major = pdata->width_major;
- touch_major = min((width_major * tp->mt_pos[i].z
- @@ -1920,7 +1918,6 @@
- dev->dev.parent = &spi->dev;
- dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- - dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- dev->absbit[BIT_WORD(ABS_MT_TRACKING_ID)] |=
- BIT_MASK(ABS_MT_TRACKING_ID);
- diff -ruN a/4.1.B.0.431//kernel/drivers/input/touchscreen/cyttsp_core.c b/4.1.B.0.479//kernel/drivers/input/touchscreen/cyttsp_core.c
- --- a/4.1.B.0.431//kernel/drivers/input/touchscreen/cyttsp_core.c 2012-06-10 23:35:47.000000000 +0900
- +++ b/4.1.B.0.479//kernel/drivers/input/touchscreen/cyttsp_core.c 2012-06-25 19:47:11.000000000 +0900
- @@ -644,7 +644,7 @@
- void handle_multi_touch(struct cyttsp_track_data *t, struct cyttsp *ts)
- {
- - u8 id;
- + u8 id, count;
- u8 i, loc;
- void (*mt_sync_func)(struct input_dev *) = ts->platform_data->mt_sync;
- @@ -657,23 +657,12 @@
- if ((ts->act_trk[id] == CY_NTCH) || (t->cur_trk[id] != CY_NTCH))
- continue;
- - input_report_abs(ts->input, ABS_MT_TRACKING_ID, id);
- - input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR, CY_NTCH);
- - input_report_key(ts->input, BTN_TOUCH, CY_NTCH);
- - input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR, t->tool_width);
- - input_report_abs(ts->input, ABS_MT_POSITION_X,
- - ts->prv_mt_pos[id][CY_XPOS]);
- - input_report_abs(ts->input, ABS_MT_POSITION_Y,
- - ts->prv_mt_pos[id][CY_YPOS]);
- - input_report_abs(ts->input, ABS_MT_PRESSURE, t->cur_mt_z[id]);
- - if (mt_sync_func)
- - mt_sync_func(ts->input);
- ts->act_trk[id] = CY_NTCH;
- ts->prv_mt_pos[id][CY_XPOS] = 0;
- ts->prv_mt_pos[id][CY_YPOS] = 0;
- }
- /* set Multi-Touch current event signals */
- - for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
- + for (count = id = 0; id < CY_NUM_MT_TCH_ID; id++) {
- if (t->cur_mt_tch[id] >= CY_NUM_TRK_ID)
- continue;
- @@ -681,7 +670,6 @@
- t->cur_mt_tch[id]);
- input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,
- t->cur_mt_z[id]);
- - input_report_key(ts->input, BTN_TOUCH, CY_TCH);
- input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR,
- t->tool_width);
- input_report_abs(ts->input, ABS_MT_POSITION_X,
- @@ -693,10 +681,16 @@
- if (mt_sync_func)
- mt_sync_func(ts->input);
- + count++;
- ts->act_trk[id] = CY_TCH;
- ts->prv_mt_pos[id][CY_XPOS] = t->cur_mt_pos[id][CY_XPOS];
- ts->prv_mt_pos[id][CY_YPOS] = t->cur_mt_pos[id][CY_YPOS];
- }
- + /* if no fingers were pressed, we need to output a MT sync so that the
- + * userspace can identify when the last finger has been removed from
- + * the device */
- + if (!count)
- + mt_sync_func(ts->input);
- return;
- no_track_id:
- @@ -793,7 +787,6 @@
- if (t->snd_trk[id] < CY_NUM_TRK_ID) {
- input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,
- t->cur_mt_z[t->snd_trk[id]]);
- - input_report_key(ts->input, BTN_TOUCH, CY_TCH);
- input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR,
- t->tool_width);
- input_report_abs(ts->input, ABS_MT_POSITION_X,
- @@ -814,7 +807,6 @@
- /* void out this touch */
- input_report_abs(ts->input, ABS_MT_TOUCH_MAJOR,
- CY_NTCH);
- - input_report_key(ts->input, BTN_TOUCH, CY_NTCH);
- input_report_abs(ts->input, ABS_MT_WIDTH_MAJOR,
- t->tool_width);
- input_report_abs(ts->input, ABS_MT_POSITION_X,
- @@ -2141,22 +2133,27 @@
- set_bit(EV_SYN, input_device->evbit);
- set_bit(EV_KEY, input_device->evbit);
- set_bit(EV_ABS, input_device->evbit);
- - set_bit(BTN_TOUCH, input_device->keybit);
- - set_bit(BTN_2, input_device->keybit);
- + if (ts->platform_data->use_st) {
- + set_bit(BTN_TOUCH, input_device->keybit);
- + set_bit(BTN_2, input_device->keybit);
- + }
- if (ts->platform_data->use_gestures)
- set_bit(BTN_3, input_device->keybit);
- - input_set_abs_params(input_device, ABS_X, 0, ts->platform_data->maxx,
- - 0, 0);
- - input_set_abs_params(input_device, ABS_Y, 0, ts->platform_data->maxy,
- - 0, 0);
- - input_set_abs_params(input_device, ABS_TOOL_WIDTH, 0,
- - CY_LARGE_TOOL_WIDTH, 0, 0);
- - input_set_abs_params(input_device, ABS_PRESSURE, 0, CY_MAXZ, 0, 0);
- - input_set_abs_params(input_device, ABS_HAT0X, 0,
- - ts->platform_data->maxx, 0, 0);
- - input_set_abs_params(input_device, ABS_HAT0Y, 0,
- - ts->platform_data->maxy, 0, 0);
- + if (ts->platform_data->use_st) {
- + input_set_abs_params(input_device, ABS_X, 0,
- + ts->platform_data->maxx, 0, 0);
- + input_set_abs_params(input_device, ABS_Y, 0,
- + ts->platform_data->maxy, 0, 0);
- + input_set_abs_params(input_device, ABS_TOOL_WIDTH, 0,
- + CY_LARGE_TOOL_WIDTH, 0, 0);
- + input_set_abs_params(input_device, ABS_PRESSURE, 0, CY_MAXZ,
- + 0, 0);
- + input_set_abs_params(input_device, ABS_HAT0X, 0,
- + ts->platform_data->maxx, 0, 0);
- + input_set_abs_params(input_device, ABS_HAT0Y, 0,
- + ts->platform_data->maxy, 0, 0);
- + }
- if (ts->platform_data->use_gestures) {
- input_set_abs_params(input_device, ABS_HAT1X, 0, CY_MAXZ,
- 0, 0);
- diff -ruN a/4.1.B.0.431//kernel/drivers/usb/gadget/epautoconf.c b/4.1.B.0.479//kernel/drivers/usb/gadget/epautoconf.c
- --- a/4.1.B.0.431//kernel/drivers/usb/gadget/epautoconf.c 2012-05-25 19:07:11.000000000 +0900
- +++ b/4.1.B.0.479//kernel/drivers/usb/gadget/epautoconf.c 2012-06-25 19:47:11.000000000 +0900
- @@ -302,6 +302,7 @@
- list_for_each_entry (ep, &gadget->ep_list, ep_list) {
- ep->driver_data = NULL;
- + ep->maxpacket = 512;
- }
- #ifdef MANY_ENDPOINTS
- in_epnum = 0;
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/Android.mk b/4.1.B.0.479//vendor/semc/hardware/felica/Android.mk
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/Android.mk 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/Android.mk 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,48 @@
- +ifeq (true, $(SEMC_CFG_FELICA_ENABLED))
- +
- +LOCAL_PATH:= $(call my-dir)
- +SAVED_LOCAL_PATH_FLC:= $(LOCAL_PATH)
- +
- +include $(CLEAR_VARS)
- +
- +# now the part that is actually built
- +
- +LOCAL_PATH_ABS_FLC := $(shell cd $(SAVED_LOCAL_PATH_FLC) && pwd)
- +
- +BUILD_ROOT_FLC := $(TARGET_OUT_INTERMEDIATES)/FELICA_OBJ
- +
- +BUILD_SUBDIRS_FLC := $(shell cd $(SAVED_LOCAL_PATH_FLC) && find . -type d)
- +BUILD_SRC_FLC := $(shell cd $(SAVED_LOCAL_PATH_FLC) && find . -name \*[ch])
- +BUILD_MK_FLC := $(shell cd $(SAVED_LOCAL_PATH_FLC) && find . -name Makefile)
- +
- +REL_SUBDIRS_FLC := $(addprefix $(SAVED_LOCAL_PATH_FLC)/, $(BUILD_SUBDIRS_FLC))
- +REL_SRC_FLC := $(addprefix $(SAVED_LOCAL_PATH_FLC)/, $(BUILD_SRC_FLC))
- +REL_MK_FLC := $(addprefix $(SAVED_LOCAL_PATH_FLC)/, $(BUILD_MK_FLC))
- +
- +$(BUILD_ROOT_FLC)/semc_felica.ko: $(PRODUCT_OUT)/kernel prep_flc
- + @(cd $(BUILD_ROOT_FLC); $(MAKE) KERNEL_DIR=$(ANDROID_PRODUCT_OUT)/obj/KERNEL_OBJ -f Makefile)
- +
- +prep_flc: subdirs_flc src_flc mk_flc
- +
- +subdirs_flc: $(REL_SUBDIRS_FLC)
- + @(for i in $(BUILD_SUBDIRS_FLC); do mkdir -p $(BUILD_ROOT_FLC)/$$i; done)
- +
- +src_flc: $(REL_SRC_FLC) subdirs_flc
- + @(for i in $(BUILD_SRC_FLC); do test -e $(BUILD_ROOT_FLC)/$$i || ln -sf $(LOCAL_PATH_ABS_FLC)/$$i $(BUILD_ROOT_FLC)/$$i; done)
- +
- +mk_flc: $(REL_MK_FLC) subdirs_flc
- + @(for i in $(BUILD_MK_FLC); do test -e $(BUILD_ROOT_FLC)/$$i || ln -sf $(LOCAL_PATH_ABS_FLC)/$$i $(BUILD_ROOT_FLC)/$$i; done)
- +
- +# copy the modules
- +
- +files := semc_felica.ko
- +
- +copy_to := $(addprefix $(TARGET_OUT)/lib/modules/,$(files))
- +copy_from := $(addprefix $(BUILD_ROOT_FLC)/,$(files))
- +
- +$(TARGET_OUT)/lib/modules/%.ko : $(BUILD_ROOT_FLC)/%.ko | $(ACP)
- + $(transform-prebuilt-to-target)
- +
- +ALL_PREBUILT += $(copy_to)
- +
- +endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/Makefile b/4.1.B.0.479//vendor/semc/hardware/felica/Makefile
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/Makefile 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/Makefile 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,29 @@
- +#
- +# Makefile for FeliCa kernel module
- +#
- +# Copyright 2010 Sony Ericsson Mobile Communications Japan Inc.
- +# All rights, including trade secret rights, reserved.
- +#
- +
- +# environment variables
- +CROSS_COMPILE := arm-eabi-
- +ARCH := arm
- +PWD := $(shell pwd)
- +
- +obj-m = semc_felica.o
- +
- +semc_felica-objs = felica_master.o \
- + felica_uart.o felica_statemachine.o \
- + msm_uartdm.o felica_rxbuf.o felica_txbuf.o msm_uartmux.o \
- + msm_felica_cen.o \
- + felica_pon.o \
- + felica_rfs.o \
- + felica_int.o \
- + felica_rws.o
- +
- +all:
- + $(MAKE) CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) -C $(KERNEL_DIR) M=$(PWD) modules
- +
- +clean:
- + $(MAKE) CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) -C $(KERNEL_DIR) M=$(PWD) clean
- +
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_cen.h b/4.1.B.0.479//vendor/semc/hardware/felica/felica_cen.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_cen.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_cen.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,24 @@
- +/* vendor/semc/hardware/felica/felica_cen.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _FELICA_CEN_H
- +#define _FELICA_CEN_H
- +
- +
- +#define UDELAY_CEN_WRITE 100
- +
- +struct felica_cen_pfdata;
- +
- +int felica_cen_probe_func(struct felica_cen_pfdata *);
- +void felica_cen_remove_func(void);
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_int.c b/4.1.B.0.479//vendor/semc/hardware/felica/felica_int.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_int.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_int.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,212 @@
- +/* vendor/semc/hardware/felica/felica_int.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/types.h>
- +#include <linux/stddef.h>
- +#include <linux/mfd/pmic8058.h>
- +#include <linux/uaccess.h>
- +#include <linux/gpio.h>
- +#include <linux/interrupt.h>
- +#include <mach/irqs.h>
- +#include <linux/switch.h>
- +#include <linux/workqueue.h>
- +#include "semc_felica_ext.h"
- +#include "felica_int.h"
- +
- +#define PRT_NAME "felica int"
- +#define INT_LOW 0x0
- +#define INT_HIGH 0x1
- +#define DEFAULT_INT_STATE INT_HIGH
- +
- +struct felica_int_data {
- + struct felica_int_pfdata *pfdata;
- + struct switch_dev swdev;
- + struct work_struct work_int;
- + spinlock_t lock_int;
- +};
- +
- +static struct felica_int_data *flint;
- +
- +/**
- + * @brief Interrupt handler of FeliCa INT controller
- + * @details This function executes;\n
- + * # Disable INT interrupt\n
- + * # Schedule work for FeliCa push (keventd_wq)
- + * @param irq : (unused)
- + * @param dev : (unused)
- + * @retval IRQ_HANDLED : Success
- + * @note
- + */
- +static irqreturn_t felica_int_irq_handler(int irq, void *dev)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Disable INT interrupt */
- + disable_irq_nosync(flint->pfdata->irq_int);
- + /* Schedule work for FeliCa push (keventd_wq) */
- + schedule_work(&flint->work_int);
- +
- + return IRQ_HANDLED;
- +}
- +
- +/**
- + * @brief Interrupt work description of FeliCa INT controller
- + * @details This function executes;\n
- + * # Read INT GPIO\n
- + * # Update value of the switch device\n
- + * # Enable INT interrupt\n
- + * @param work : (unused)
- + * @retval N/A
- + * @note
- + */
- +static void felica_int_exec(struct work_struct *work)
- +{
- + int state;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Read INT GPIO */
- + state = gpio_get_value_cansleep(flint->pfdata->gpio_int);
- + if (INT_LOW == state || INT_HIGH == state) {
- + /* Update value of the switch device */
- + switch_set_state(&flint->swdev, state);
- + pr_debug(PRT_NAME ": INT state = %d\n", state);
- + /* Enable INT interrupt */
- + enable_irq(flint->pfdata->irq_int);
- + } else
- + pr_err(PRT_NAME ": Error. Cannot read INT GPIO.\n");
- +}
- +
- +/**
- + * @brief Initialize FeliCa INT controller
- + * @details This function executes;\n
- + * # Check INT platform data\n
- + * # Alloc and init INT controller's data\n
- + * # Init work of FeliCa push\n
- + * # Request INT GPIO\n
- + * # Request IRQ for INT GPIO\n
- + * # Enable IRQ wake for INT GPIO\n
- + * # Create INT switch device (felica_push)\n
- + * # Set default state of the device
- + * @param pfdata : Pointer to INT platform data
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -EINVAL = No platform data\n
- + * -ENOMEM = No enough memory / Cannot create switch dev\n
- + * -ENODEV = GPIO request failed\n
- + * -EIO = IRQ request failed / Enabling IRQ wake failed
- + */
- +int felica_int_probe_func(struct felica_int_pfdata *pfdata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check INT platform data */
- + if (!pfdata) {
- + pr_err(PRT_NAME ": Error. No platform data for INT.\n");
- + return -EINVAL;
- + }
- +
- + /* Alloc and init INT controller's data */
- + flint = kzalloc(sizeof(struct felica_int_data), GFP_KERNEL);
- + if (!flint) {
- + pr_err(PRT_NAME ": Error. No enough mem for INT.\n");
- + ret = -ENOMEM;
- + goto err_alloc_int_data;
- + }
- + flint->pfdata = pfdata;
- +
- + /* Init work of FeliCa push */
- + INIT_WORK(&flint->work_int, felica_int_exec);
- +
- + /* Request INT GPIO */
- + ret = gpio_request(flint->pfdata->gpio_int, "felica_int");
- + if (ret) {
- + pr_err(PRT_NAME ": Error. INT GPIO request failed.\n");
- + ret = -ENODEV;
- + goto err_request_int_gpio;
- + }
- + ret = gpio_direction_input(flint->pfdata->gpio_int);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. INT GPIO direction failed.\n");
- + ret = -ENODEV;
- + goto err_direction_int_gpio;
- + }
- +
- + /* Request IRQ for INT GPIO */
- + ret = request_irq(flint->pfdata->irq_int, felica_int_irq_handler,
- + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "felica_irq", NULL);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Request IRQ failed.\n");
- + ret = -EIO;
- + goto err_request_int_irq;
- + }
- +
- + /* Enable IRQ wake */
- + ret = enable_irq_wake(flint->pfdata->irq_int);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Enabling IRQ wake failed.\n");
- + ret = -EIO;
- + goto err_enable_irq_wake;
- + }
- +
- + /* Create INT switch device (felica_push) */
- + flint->swdev.name = "felica_push";
- + if (switch_dev_register(&flint->swdev)) {
- + pr_err(PRT_NAME ": Error. Cannot create switch dev\n");
- + ret = -ENOMEM;
- + goto err_create_switch_dev;
- + }
- +
- + /* Set dafault state of the device */
- + switch_set_state(&flint->swdev, DEFAULT_INT_STATE);
- +
- + return 0;
- +
- +err_create_switch_dev:
- + disable_irq_wake(flint->pfdata->irq_int);
- +err_enable_irq_wake:
- + free_irq(flint->pfdata->irq_int, NULL);
- +err_request_int_irq:
- +err_direction_int_gpio:
- + gpio_free(flint->pfdata->gpio_int);
- +err_request_int_gpio:
- + kfree(flint);
- +err_alloc_int_data:
- + return ret;
- +}
- +
- +/**
- + * @brief Terminate FeliCa INT controller
- + * @details This function executes;\n
- + * # Unregister switch device (felica_push)\n
- + * # Release IRQ for INT GPIO\n
- + * # Release INT GPIO resource\n
- + * # Release INT controller's data
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_int_remove_func(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + switch_dev_unregister(&flint->swdev);
- + disable_irq_wake(flint->pfdata->irq_int);
- + free_irq(flint->pfdata->irq_int, NULL);
- + gpio_free(flint->pfdata->gpio_int);
- + kfree(flint);
- +}
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_int.h b/4.1.B.0.479//vendor/semc/hardware/felica/felica_int.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_int.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_int.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,21 @@
- +/* vendor/semc/hardware/felica/felica_int.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _FELICA_INT_H
- +#define _FELICA_INT_H
- +
- +struct felica_int_pfdata;
- +
- +int felica_int_probe_func(struct felica_int_pfdata *);
- +void felica_int_remove_func(void);
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_master.c b/4.1.B.0.479//vendor/semc/hardware/felica/felica_master.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_master.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_master.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,226 @@
- +/* vendor/semc/hardware/felica/felica_master.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/types.h>
- +#include <linux/platform_device.h>
- +#include "semc_felica_ext.h"
- +#include "felica_uart.h"
- +#include "felica_cen.h"
- +#include "felica_pon.h"
- +#include "felica_rfs.h"
- +#include "felica_int.h"
- +#include "felica_rws.h"
- +
- +#define DRV_NAME "felica driver"
- +#define DRV_VERSION "0.2"
- +#define PRT_NAME "felica master"
- +
- +/**
- + * @brief Probe function of FeliCa driver
- + * @details This function executes;\n
- + * # Load platform data of FeliCa driver\n
- + * # GPIO setting of MSM & PM\n
- + * # Call initialization functions of each controller
- + * @param pdev : Pointer to data of FeliCa platform device
- + * @retval 0 : Success
- + * @retval Negative : Failure
- + * @note
- + */
- +static int felica_probe(struct platform_device *pdev)
- +{
- + int ret;
- + struct felica_platform_data *flc_pfdata;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Load platform data of FeliCa driver */
- + flc_pfdata = pdev->dev.platform_data;
- + if (NULL == flc_pfdata) {
- + pr_err(PRT_NAME ": Error. No platform data.\n");
- + ret = -EINVAL;
- + goto err_get_platform_data;
- + }
- +
- + /* GPIO setting of MSM & PM */
- + if (flc_pfdata->gpio_init) {
- + ret = flc_pfdata->gpio_init();
- + if (ret && -EBUSY != ret) {
- + pr_err(PRT_NAME ": Error. GPIO init failed.\n");
- + goto error_gpio_init;
- + }
- + }
- +
- + /* Call initialization functions of each controller */
- + ret = felica_uart_probe_func(&flc_pfdata->uart_pfdata);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. UART probe failure.\n");
- + goto err_uart_probe;
- + }
- +
- + ret = felica_cen_probe_func(&flc_pfdata->cen_pfdata);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. CEN probe failure.\n");
- + goto err_cen_probe;
- + }
- +
- + ret = felica_pon_probe_func(&flc_pfdata->pon_pfdata);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. PON probe failure.\n");
- + goto err_pon_probe;
- + }
- +
- + ret = felica_rfs_probe_func(&flc_pfdata->rfs_pfdata);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. RFS probe failure.\n");
- + goto err_rfs_probe;
- + }
- +
- + ret = felica_int_probe_func(&flc_pfdata->int_pfdata);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. INT probe failure.\n");
- + goto err_int_probe;
- + }
- +
- + ret = felica_rws_probe_func();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. RWS probe failure.\n");
- + goto err_rws_probe;
- + }
- +
- + return 0;
- +
- +/* Error handling */
- +err_rws_probe:
- + felica_int_remove_func();
- +err_int_probe:
- + felica_rfs_remove_func();
- +err_rfs_probe:
- + felica_pon_remove_func();
- +err_pon_probe:
- + felica_cen_remove_func();
- +err_cen_probe:
- + felica_uart_remove_func();
- +err_uart_probe:
- +error_gpio_init:
- +err_get_platform_data:
- + return ret;
- +}
- +
- +/**
- + * @brief Remove function of FeliCa driver
- + * @details This function executes;\n
- + * # Call termination functions of each controller
- + * @param pdev : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +static int felica_remove(struct platform_device *pdev)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + felica_rws_remove_func();
- + felica_int_remove_func();
- + felica_rfs_remove_func();
- + felica_pon_remove_func();
- + felica_cen_remove_func();
- + felica_uart_remove_func();
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Suspend function of FeliCa driver
- + * @param pdev : (unused)
- + * @param message
- + * @retval 0
- + * @note
- + */
- +static int felica_suspend(struct platform_device *pdev,
- + pm_message_t message)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Resume function of FeliCa driver
- + * @param pdev : (unused)
- + * @retval 0
- + * @note
- + */
- +static int felica_resume(struct platform_device *pdev)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Platform driver data structure of FeliCa driver
- + */
- +static struct platform_driver semc_felica_driver = {
- + .probe = felica_probe,
- + .remove = felica_remove,
- + .suspend = felica_suspend,
- + .resume = felica_resume,
- + .driver = {
- + .name = "semc_felica",
- + .owner = THIS_MODULE,
- + },
- +};
- +
- +/**
- + * @brief Init function of FeliCa driver
- + * @details This function executes;\n
- + * # platform driver registration of FeliCa driver
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Failure
- + * @note
- + */
- +static int __init felica_init(void)
- +{
- + int ret;
- +
- + pr_info(PRT_NAME ": FeliCa driver ver %s being loaded.\n",
- + DRV_VERSION);
- +
- + ret = platform_driver_register(&semc_felica_driver);
- + return ret;
- +}
- +
- +/**
- + * @brief Exit function of FeliCa driver
- + * @details This function executes;\n
- + * # platform driver unregistration of FeliCa driver
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +static void __exit felica_exit(void)
- +{
- + pr_info(PRT_NAME ": %s\n", __func__);
- +
- + platform_driver_unregister(&semc_felica_driver);
- +}
- +
- +module_init(felica_init);
- +module_exit(felica_exit);
- +
- +MODULE_VERSION(DRV_VERSION);
- +MODULE_AUTHOR("SEMC");
- +MODULE_DESCRIPTION("FeliCa driver");
- +MODULE_LICENSE("GPL");
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_pon.c b/4.1.B.0.479//vendor/semc/hardware/felica/felica_pon.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_pon.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_pon.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,258 @@
- +/* vendor/semc/hardware/felica/felica_pon.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/types.h>
- +#include <linux/stddef.h>
- +#include <linux/fs.h>
- +#include <linux/err.h>
- +#include <linux/miscdevice.h>
- +#include <linux/mfd/pmic8058.h>
- +#include <linux/delay.h>
- +#include <linux/uaccess.h>
- +#include <linux/gpio.h>
- +#include "semc_felica_ext.h"
- +#include "felica_pon.h"
- +#include "felica_rws.h"
- +
- +#define PRT_NAME "felica pon"
- +#define PON_LOW 0x00
- +#define PON_HIGH 0x01
- +
- +struct felica_pon_data {
- + struct felica_pon_pfdata *pfdata;
- +};
- +
- +static struct felica_pon_data *flpon;
- +
- +/**
- + * @brief Open file operation of FeliCa PON controller
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +static int felica_pon_open(struct inode *inode, struct file *file)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Close file operation of FeliCa PON controller
- + * @details This module is responsible for the following roles:\n
- + * # Forcedly, write Low to PON GPIO\n
- + * # Forcedly, turn off TVDD
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +static int felica_pon_release(struct inode *inode, struct file *file)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Forcedly, write Low to PON GPIO */
- + gpio_set_value_cansleep(flpon->pfdata->gpio_pon, PON_LOW);
- +
- + /* Forcedly, turn off TVDD */
- + if (flpon->pfdata->tvdd_off)
- + flpon->pfdata->tvdd_off();
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Write file operation of FeliCa PON controller
- + * @details This function executes;\n
- + * # Copy value from user space\n
- + * # [When writing High,]\n
- + * # | Write High to PON GPIO\n
- + * # | [Params meet the condition,] turn on TVDD.\n
- + * # [When writing Low,]\n
- + * # | Write Low to PON GPIO\n
- + * # | Forcedly, turn off TVDD.\n
- + * @param file : (unused)
- + * @param buf : Source of the written data
- + * @param count : Data length must be 1 Byte.
- + * @param offset : (unused)
- + * @retval 1 : Success
- + * @retval Negative : Failure\n
- + * -EINVAL = Invalid argument\n
- + * -EFAULT = Cannot copy data from user space\n
- + * -EIO = Cannot control VREG
- + * @note
- + */
- +static ssize_t felica_pon_write(struct file *file, const char __user *buf,
- + size_t count, loff_t *offset)
- +{
- + char kbuf;
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (1 != count || !buf) {
- + pr_err(PRT_NAME ": Error. Invalid arg @PON write.\n");
- + return -EINVAL;
- + }
- +
- + /* Copy value from user space */
- + if (copy_from_user(&kbuf, buf, 1)) {
- + pr_err(PRT_NAME ": Error. copy_from_user failure.\n");
- + return -EFAULT;
- + }
- +
- + if (PON_HIGH == kbuf) {
- + /* Write High to PON GPIO */
- + gpio_set_value_cansleep(flpon->pfdata->gpio_pon, PON_HIGH);
- + if (((PARAM_OFF == st_usbcon) && (PARAM_OFF == st_airplane))
- + || (PARAM_ON == ta_rwusb)) {
- + pr_debug(PRT_NAME ": TVDD --> ON.\n");
- + /* Turn on TVDD */
- + if (flpon->pfdata->tvdd_on) {
- + ret = flpon->pfdata->tvdd_on();
- + if (ret) {
- + pr_err(PRT_NAME
- + ": Error. Cannot ctrl TVDD.\n");
- + return -EIO;
- + }
- + }
- + } else {
- + pr_debug(PRT_NAME ": TVDD == OFF.\n");
- + }
- + } else if (PON_LOW == kbuf) {
- + /* Write LOW to PON GPIO */
- + gpio_set_value_cansleep(flpon->pfdata->gpio_pon, PON_LOW);
- + /* Turn off TVDD */
- + if (flpon->pfdata->tvdd_off)
- + flpon->pfdata->tvdd_off();
- + } else {
- + pr_err(PRT_NAME ": Error. Invalid val @PON write.\n");
- + return -EINVAL;
- + }
- +
- + /* 1 byte write */
- + return 1;
- +}
- +
- +/***************** PON FOPS ****************************/
- +static const struct file_operations felica_pon_fops = {
- + .owner = THIS_MODULE,
- + .read = NULL,
- + .write = felica_pon_write,
- + .ioctl = NULL,
- + .open = felica_pon_open,
- + .release = felica_pon_release,
- + .fsync = NULL,
- +};
- +
- +static struct miscdevice felica_pon_device = {
- + .minor = MISC_DYNAMIC_MINOR,
- + .name = "felica_pon",
- + .fops = &felica_pon_fops,
- +};
- +
- +/**
- + * @brief Initilialize FeliCa PON controller
- + * @details This function executes;\n
- + * # Check PON platform data\n
- + * # Alloc and init PON controller's data\n
- + * # Request PON GPIO\n
- + * # Disable TVDD vreg device\n
- + * # Create PON character device (/dev/felica_pon)
- + * @param pfdata : Pointer to PON platform data
- + * @retval 0 : Success
- + * @retval Negative : Initialization failed.\n
- + * -EINVAL = No platform data\n
- + * -ENODEV = Requesting GPIO failed / Getting TVDD dev failed\n
- + * -ENOMEM = No enough memory / Cannot create char dev
- + * -EIO = Cannot control VREG
- + * @note
- + */
- +int felica_pon_probe_func(struct felica_pon_pfdata *pfdata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check PON platform data */
- + if (!pfdata) {
- + pr_err(PRT_NAME ": Error. No platform data for PON.\n");
- + return -EINVAL;
- + }
- +
- + /* Alloc and init PON controller's data */
- + flpon = kzalloc(sizeof(struct felica_pon_data), GFP_KERNEL);
- + if (!flpon) {
- + pr_err(PRT_NAME ": Error. No enough mem for PON.\n");
- + ret = -ENOMEM;
- + goto err_alloc_pon_data;
- + }
- + flpon->pfdata = pfdata;
- +
- + /* Request PON GPIO */
- + ret = gpio_request(flpon->pfdata->gpio_pon, "felica_pon");
- + if (ret) {
- + pr_err(PRT_NAME ": Error. PON GPIO request failed.\n");
- + ret = -ENODEV;
- + goto err_request_pon_gpio;
- + }
- + ret = gpio_direction_output(flpon->pfdata->gpio_pon, PON_LOW);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. PON GPIO direction failed.\n");
- + ret = -ENODEV;
- + goto err_direction_pon_gpio;
- + }
- +
- + /* Disable TVDD vreg device */
- + if (flpon->pfdata->tvdd_off)
- + flpon->pfdata->tvdd_off();
- +
- + /* Create PON character device (/dev/felica_pon) */
- + if (misc_register(&felica_pon_device)) {
- + pr_err(PRT_NAME ": Error. Cannot register PON.\n");
- + ret = -ENOMEM;
- + goto err_create_pon_dev;
- + }
- +
- + return 0;
- +
- +err_create_pon_dev:
- +err_direction_pon_gpio:
- + gpio_free(flpon->pfdata->gpio_pon);
- +err_request_pon_gpio:
- + kfree(flpon);
- +err_alloc_pon_data:
- + return ret;
- +}
- +
- +/**
- + * @brief Terminate FeliCa PON controller
- + * @details This function executes;\n
- + * # Deregister PON character device (/dev/felica_pon)\n
- + * # Release PON GPIO resource\n
- + * # Release PON controller's data
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_pon_remove_func(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + misc_deregister(&felica_pon_device);
- + gpio_free(flpon->pfdata->gpio_pon);
- + kfree(flpon);
- +}
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_pon.h b/4.1.B.0.479//vendor/semc/hardware/felica/felica_pon.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_pon.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_pon.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,21 @@
- +/* vendor/semc/hardware/felica/felica_pon.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _FELICA_PON_H
- +#define _FELICA_PON_H
- +
- +struct felica_pon_pfdata;
- +
- +int felica_pon_probe_func(struct felica_pon_pfdata *);
- +void felica_pon_remove_func(void);
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rfs.c b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rfs.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rfs.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rfs.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,216 @@
- +/* vendor/semc/hardware/felica/felica_rfs.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/types.h>
- +#include <linux/stddef.h>
- +#include <linux/fs.h>
- +#include <linux/miscdevice.h>
- +#include <linux/mfd/pmic8058.h>
- +#include <linux/uaccess.h>
- +#include <linux/gpio.h>
- +#include "semc_felica_ext.h"
- +#include "felica_rfs.h"
- +
- +#define PRT_NAME "felica rfs"
- +#define RFS_GPIO_L 0
- +#define RFS_GPIO_H 1
- +#define RFS_VAL_L 0x00
- +#define RFS_VAL_H 0x01
- +
- +struct felica_rfs_data {
- + struct felica_rfs_pfdata *pfdata;
- +};
- +
- +static struct felica_rfs_data *flrfs;
- +
- +/**
- + * @brief Open file operation of FeliCa RFS controller
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +static int felica_rfs_open(struct inode *inode, struct file *file)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Close file operation of FeliCa RFS controller
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +static int felica_rfs_release(struct inode *inode, struct file *file)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Read file operation of FeliCa RFS controller
- + * @details This function executes;\n
- + * # Read RFS GPIO value\n
- + * # Copy the value to user space
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval 1 : Success
- + * @retval Negative : Failure\n
- + * -EINVAL = Invalid argument\n
- + * -EIO = GPIO read error\n
- + * -EFAULT = Cannot copy data to user space
- + * @note
- + */
- +static ssize_t felica_rfs_read(struct file *file, char __user *buf,
- + size_t count, loff_t *offset)
- +{
- + char kbuf;
- + int gpio_val;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (1 != count || !buf) {
- + pr_err(PRT_NAME ": Error. Invalid arg @RFS read.\n");
- + return -EINVAL;
- + }
- +
- + /* Read RFS GPIO value */
- + gpio_val = gpio_get_value_cansleep(flrfs->pfdata->gpio_rfs);
- + if (RFS_GPIO_L == gpio_val)
- + kbuf = RFS_VAL_H;
- + else if (RFS_GPIO_H == gpio_val)
- + kbuf = RFS_VAL_L;
- + else {
- + pr_err(PRT_NAME ": Error. Invalid GPIO value @RFS read.\n");
- + return -EIO;
- + }
- +
- + /* Copy the value to user space */
- + if (copy_to_user(buf, &kbuf, 1)) {
- + pr_err(PRT_NAME ": Error. copy_to_user failure.\n");
- + return -EFAULT;
- + }
- +
- + /* 1 byte read */
- + return 1;
- +}
- +
- +/***************** RFS FOPS ****************************/
- +static const struct file_operations felica_rfs_fops = {
- + .owner = THIS_MODULE,
- + .read = felica_rfs_read,
- + .write = NULL,
- + .ioctl = NULL,
- + .open = felica_rfs_open,
- + .release = felica_rfs_release,
- + .fsync = NULL,
- +};
- +
- +static struct miscdevice felica_rfs_device = {
- + .minor = MISC_DYNAMIC_MINOR,
- + .name = "felica_rfs",
- + .fops = &felica_rfs_fops,
- +};
- +
- +/**
- + * @brief Initilialize FeliCa RFS controller
- + * @details This function executes;\n
- + * # Check RFS platform data\n
- + * # Alloc and init RFS controller's data\n
- + * # Request RFS GPIO\n
- + * # Create RFS character device (/dev/felica_rfs)
- + * @param pfdata : Pointer to RFS platform data
- + * @retval 0 : Success
- + * @retval Negative : Initialization failed.\n
- + * -EINVAL = No platform data\n
- + * -ENODEV = Requesting GPIO failed\n
- + * -ENOMEM = No enough memory / Cannot create char dev
- + * @note
- + */
- +int felica_rfs_probe_func(struct felica_rfs_pfdata *pfdata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check RFS platform data */
- + if (!pfdata) {
- + pr_err(PRT_NAME ": Error. No platform data for RFS.\n");
- + return -EINVAL;
- + }
- +
- + /* Alloc and init RFS controller's data */
- + flrfs = kzalloc(sizeof(struct felica_rfs_data), GFP_KERNEL);
- + if (!flrfs) {
- + pr_err(PRT_NAME ": Error. No enough mem for RFS.\n");
- + ret = -ENOMEM;
- + goto err_alloc_rfs_data;
- + }
- + flrfs->pfdata = pfdata;
- +
- + /* Request RFS GPIO */
- + ret = gpio_request(flrfs->pfdata->gpio_rfs, "felica_rfs");
- + if (ret) {
- + pr_err(PRT_NAME ": Error. RFS GPIO request failed.\n");
- + ret = -ENODEV;
- + goto err_request_rfs_gpio;
- + }
- + ret = gpio_direction_input(flrfs->pfdata->gpio_rfs);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. RFS GPIO direction failed.\n");
- + ret = -ENODEV;
- + goto err_direction_rfs_gpio;
- + }
- +
- + /* Create RFS character device (/dev/felica_rfs) */
- + if (misc_register(&felica_rfs_device)) {
- + pr_err(PRT_NAME ": Error. Cannot register RFS.\n");
- + ret = -ENOMEM;
- + goto err_create_rfs_dev;
- + }
- +
- + return 0;
- +
- +err_create_rfs_dev:
- +err_direction_rfs_gpio:
- + gpio_free(flrfs->pfdata->gpio_rfs);
- +err_request_rfs_gpio:
- + kfree(flrfs);
- +err_alloc_rfs_data:
- + return ret;
- +}
- +
- +/**
- + * @brief Terminate FeliCa RFS controller
- + * @details This function executes;\n
- + * # Deregister RFS character device (/dev/felica_rfs)\n
- + * # Release RFS GPIO resource\n
- + * # Release RFS controller's data
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_rfs_remove_func(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + misc_deregister(&felica_rfs_device);
- + gpio_free(flrfs->pfdata->gpio_rfs);
- + kfree(flrfs);
- +}
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rfs.h b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rfs.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rfs.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rfs.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,21 @@
- +/* vendor/semc/hardware/felica/felica_rfs.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _FELICA_RFS_H
- +#define _FELICA_RFS_H
- +
- +struct felica_rfs_pfdata;
- +
- +int felica_rfs_probe_func(struct felica_rfs_pfdata *);
- +void felica_rfs_remove_func(void);
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rws.c b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rws.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rws.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rws.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,190 @@
- +/* vendor/semc/hardware/felica/felica_rws.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/types.h>
- +#include <linux/stddef.h>
- +#include <linux/fs.h>
- +#include <linux/miscdevice.h>
- +#include <linux/uaccess.h>
- +#include "felica_rws.h"
- +
- +#define PRT_NAME "felica rws"
- +#define ONEBYTE 1
- +#define RWS_LOW 0x0
- +#define RWS_HIGH 0x1
- +
- +/* Module parameters for Reader/Writer mode */
- +unsigned int st_usbcon;
- +unsigned int st_airplane;
- +unsigned int ta_rwusb;
- +
- +module_param(st_usbcon, uint, S_IRUGO | S_IWUSR);
- +MODULE_PARM_DESC(st_usbcon, "USB status for FeliCa");
- +module_param(st_airplane, uint, S_IRUGO | S_IWUSR);
- +MODULE_PARM_DESC(st_airplane, "Airplane mode status for FeliCa");
- +module_param(ta_rwusb, uint, S_IRUGO | S_IWUSR);
- +MODULE_PARM_DESC(ta_rwusb, "FeliCa RW disabling for USB");
- +
- +/**
- + * @brief Open file operation of FeliCa RWS controller
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +static int felica_rws_open(struct inode *inode, struct file *file)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Close file operation of FeliCa RWS controller
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +static int felica_rws_release(struct inode *inode, struct file *file)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Read file operation of FeliCa RWS controller
- + * @details This function executes;\n
- + * # Check R/W module parameters\n
- + * # Determine RWS value\n
- + * # Copy the value to user space
- + * @param file : (unused)
- + * @param buf : Destination of the read data
- + * @param count : Data length must be 1
- + * @param offset : (unused)
- + * @retval ONEBYTE(1): Success.
- + * @retval Negative : Failure\n
- + * -EINVAL = Invalid argument\n
- + * -EIO = Invalid module parameters\n
- + * -EFAULT = Cannot copy data to user space
- + * @note
- + */
- +static ssize_t felica_rws_read(struct file *file, char __user *buf,
- + size_t count, loff_t *offset)
- +{
- + char kbuf;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (ONEBYTE != count || !buf) {
- + pr_err(PRT_NAME ": Error. Invalid arg @RWS read.\n");
- + return -EINVAL;
- + }
- +
- + pr_debug(PRT_NAME ": st_usbcon = 0x%x\n", st_usbcon);
- + pr_debug(PRT_NAME ": st_airplane = 0x%x\n", st_airplane);
- + pr_debug(PRT_NAME ": ta_rwusb = 0x%x\n", ta_rwusb);
- +
- + /* Check R/W module parameters */
- + if (PARAM_OFF != st_usbcon && PARAM_ON != st_usbcon) {
- + pr_err(PRT_NAME ": Error. Invalid st_usbcon value.\n");
- + return -EIO;
- + }
- + if (PARAM_OFF != st_airplane && PARAM_ON != st_airplane) {
- + pr_err(PRT_NAME ": Error. Invalid st_airplane value.\n");
- + return -EIO;
- + }
- + if (PARAM_OFF != ta_rwusb && PARAM_ON != ta_rwusb) {
- + pr_err(PRT_NAME ": Error. Invalid ta_rwusb value.\n");
- + return -EIO;
- + }
- +
- + /* Determine RWS value */
- + if ((PARAM_ON == st_usbcon || PARAM_ON == st_airplane)
- + && PARAM_OFF == ta_rwusb)
- + kbuf = RWS_HIGH;
- + else
- + kbuf = RWS_LOW;
- +
- + /* Copy the value to user space */
- + if (copy_to_user(buf, &kbuf, ONEBYTE)) {
- + pr_err(PRT_NAME ": Error. copy_to_user failure.\n");
- + return -EFAULT;
- + }
- +
- + /* 1 byte read */
- + return ONEBYTE;
- +}
- +
- +/***************** RWS FOPS ****************************/
- +static const struct file_operations felica_rws_fops = {
- + .owner = THIS_MODULE,
- + .read = felica_rws_read,
- + .write = NULL,
- + .ioctl = NULL,
- + .open = felica_rws_open,
- + .release = felica_rws_release,
- +};
- +
- +static struct miscdevice felica_rws_device = {
- + .minor = MISC_DYNAMIC_MINOR,
- + .name = "felica_rws",
- + .fops = &felica_rws_fops,
- +};
- +
- +/**
- + * @brief Initilialize FeliCa RWS controller
- + * @details This function executes;\n
- + * # Initialize R/W module parameters\n
- + * # Create RWS character device (/dev/felica_rws)
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Initialization failed.\n
- + * -ENOMEM = Cannot create char dev
- + * @note
- + */
- +int felica_rws_probe_func(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Initialize R/W module parameters */
- + st_usbcon = PARAM_OFF;
- + st_airplane = PARAM_OFF;
- + ta_rwusb = PARAM_OFF;
- +
- + /* Create RWS character device (/dev/felica_rws) */
- + if (misc_register(&felica_rws_device)) {
- + pr_err(PRT_NAME ": Error. Cannot register RWS.\n");
- + return -ENOMEM;
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Terminate FeliCa RWS controller
- + * @details This function executes;\n
- + * # Deregister RWS character device (/dev/felica_rws)\n
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_rws_remove_func(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + misc_deregister(&felica_rws_device);
- +}
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rws.h b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rws.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rws.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rws.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,26 @@
- +/* vendor/semc/hardware/felica/felica_rws.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _FELICA_RWS_H
- +#define _FELICA_RWS_H
- +
- +#define PARAM_OFF 0
- +#define PARAM_ON 1
- +
- +extern unsigned int st_usbcon;
- +extern unsigned int st_airplane;
- +extern unsigned int ta_rwusb;
- +
- +int felica_rws_probe_func(void);
- +void felica_rws_remove_func(void);
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rxbuf.c b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rxbuf.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rxbuf.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rxbuf.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,319 @@
- +/* vendor/semc/hardware/felica/felica_rxbuf.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/types.h>
- +#include <linux/stddef.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/dmapool.h>
- +#include <linux/uaccess.h>
- +#include "felica_rxbuf.h"
- +
- +#define PRT_NAME "rxbuf"
- +
- +/* DEBUG_RXBUF_DUMP : 0 = without dump, 1 = with dump */
- +#define DEBUG_RXBUF_DUMP 0
- +#if DEBUG_RXBUF_DUMP
- +#include <linux/string.h>
- +#endif
- +
- +struct rxbuf_slot {
- + int head;
- + int tail;
- + char *buf;
- + dma_addr_t dmabase;
- +};
- +
- +struct rxbuf_all {
- + int wp;
- + int rp;
- + struct rxbuf_slot slot[RXBUF_N];
- + int count;
- + enum {no, yes} fulfill;
- + struct dma_pool *dmapool;
- +};
- +
- +static struct rxbuf_all rxbuf;
- +
- +#if DEBUG_RXBUF_DUMP
- +static char dump[RXBUF_M * RXBUF_N];
- +#endif
- +
- +/**
- + * @brief Clear RX buffer
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_rxbuf_clear(void)
- +{
- + int i;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + rxbuf.wp = 0;
- + rxbuf.rp = 0;
- + for (i = 0; i < RXBUF_N; i++) {
- + rxbuf.slot[i].head = 0;
- + rxbuf.slot[i].tail = 0;
- + }
- + rxbuf.count = 0;
- + rxbuf.fulfill = no;
- +}
- +
- +/**
- + * @brief Count the number of the stored data in RX buffer
- + * @param N/A
- + * @retval 0/Positive : Success. the number of the stored data
- + * @retval Negative : Failure\n
- + * -ENODEV = RX buffer not initialized
- + * @note
- + */
- +int felica_rxbuf_count(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (!rxbuf.dmapool) {
- + pr_err(PRT_NAME ": Error. RX buf not initialized.\n");
- + return -ENODEV;
- + }
- +
- + return rxbuf.count;
- +}
- +
- +/**
- + * @brief Copy the stored data to User space buffer
- + * @param buf : Pointer to User space buffer
- + * @param len : Date length to copy
- + * @retval Positive : Number of the data copied successfully.
- + * @retval 0 : No data to copy
- + * @retval Negative : Failure.\n
- + * -EINVAL = Invalid arguments\n
- + * -ENODEV = RX buffer not initialized\n
- + * -EFAULT = Data copy error
- + */
- +int felica_rxbuf_gets(char __user *buf, int len)
- +{
- + int ret;
- + int cnt = 0;
- + int rest, srest;
- + int cpnum;
- +
- +#if DEBUG_RXBUF_DUMP
- + int i;
- +#endif
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if ((0 >= len) || (NULL == buf)) {
- + pr_err(PRT_NAME ": Error. Invalid argument.\n");
- + return -EINVAL;
- + }
- + if (!rxbuf.dmapool) {
- + pr_err(PRT_NAME ": Error. RX buf not initialized.\n");
- + return -ENODEV;
- + }
- +
- + if (0 == rxbuf.count)
- + return 0;
- +
- + while (1) {
- + rest = len - cnt;
- + if (0 == rest)
- + break;
- + srest = rxbuf.slot[rxbuf.rp].head - rxbuf.slot[rxbuf.rp].tail;
- + cpnum = (rest < srest) ? rest : srest ;
- + ret = copy_to_user(buf + cnt, rxbuf.slot[rxbuf.rp].buf
- + + rxbuf.slot[rxbuf.rp].tail, cpnum);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. copy_to_user failure.\n");
- + return -EFAULT;
- + }
- +
- +#if DEBUG_RXBUF_DUMP
- + memcpy(dump + cnt, rxbuf.slot[rxbuf.rp].buf
- + + rxbuf.slot[rxbuf.rp].tail, cpnum);
- +#endif
- +
- + rxbuf.slot[rxbuf.rp].tail += cpnum;
- + cnt += cpnum;
- + if (rxbuf.slot[rxbuf.rp].tail == rxbuf.slot[rxbuf.rp].head) {
- + rxbuf.slot[rxbuf.rp].tail = 0;
- + rxbuf.slot[rxbuf.rp].head = 0;
- + rxbuf.rp++;
- + rxbuf.rp %= RXBUF_N;
- + rxbuf.fulfill = no;
- + }
- + if (rxbuf.rp == rxbuf.wp)
- + break;
- + }
- + rxbuf.count -= cnt;
- +
- +#if DEBUG_RXBUF_DUMP
- + printk("RXgets dump: ");
- + for (i = 0; i < cnt; i++)
- + printk("%02x ", dump[i]);
- + printk("\n");
- +#endif
- +
- + return cnt;
- +}
- +
- +/**
- + * @brief Return DMA address pointer to push data
- + * @param N/A
- + * @retval Valid-address : DMA address to push
- + * @retval 0 : No space to push
- + */
- +dma_addr_t felica_rxbuf_push_pointer(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (yes == rxbuf.fulfill || !rxbuf.dmapool)
- + return 0;
- +
- + return rxbuf.slot[rxbuf.wp].dmabase;
- +}
- +
- +/**
- + * @brief Return data length possible to push
- + * @param N/A
- + * @retval Positive : Data length of the space to push
- + * @retval 0 : No space to push
- + * @retval Negative : Failure\n
- + * -ENODEV = RX buffer not initialized
- + * @note
- + */
- +int felica_rxbuf_push_length(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (!rxbuf.dmapool) {
- + pr_err(PRT_NAME ": Error. RX buf not initialized.\n");
- + return -ENODEV;
- + }
- +
- + if (yes == rxbuf.fulfill)
- + return 0;
- +
- + return RXBUF_M;
- +}
- +
- +/**
- + * @brief Update RX buffer status according to the pushed data.
- + * @param len : Data length already pushed
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -EIO = Invalid arguments\n
- + * -ENODEV = RX buffer not initialized.\n
- + * -EFAULT = RX buf is already fulfilled.
- + * @note
- + */
- +int felica_rxbuf_push_status_update(int len)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if ((0 >= len) || (RXBUF_M < len)) {
- + pr_err(PRT_NAME ": Error. Invalid arg for push status.\n");
- + return -EINVAL;
- + }
- + if (!rxbuf.dmapool) {
- + pr_err(PRT_NAME ": Error. RX buf not initialized.\n");
- + return -ENODEV;
- + }
- +
- + if (yes == rxbuf.fulfill) {
- + pr_err(PRT_NAME ": Error. RX buf is already fulfilled.\n");
- + return -EFAULT;
- + }
- +
- + rxbuf.slot[rxbuf.wp].head = len;
- + rxbuf.wp++;
- + rxbuf.wp %= RXBUF_N;
- + if (rxbuf.wp == rxbuf.rp)
- + rxbuf.fulfill = yes;
- + rxbuf.count += len;
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Initialize & alloc RX buffer
- + * @details This function executes;\n
- + * # Create DMA pool\n
- + * # Alloc RX buffer\n
- + * # Call RX buffer clear
- + * @param N/A
- + * @retval 0 : Success
- + * @retval -ENOMEM : Error, no enough memory.
- + * @note
- + */
- +int felica_rxbuf_init(void)
- +{
- + int i;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + rxbuf.dmapool = dma_pool_create(DMAPOOL_NAME, NULL, DMAPOOL_SIZE,
- + DMAPOOL_ALIGN, DMAPOOL_ALIGN * RXBUF_N);
- + if (!rxbuf.dmapool) {
- + pr_err(PRT_NAME ": Error. Cannot create DMA pool for RXbuf.");
- + return -ENOMEM;
- + }
- + for (i = 0; i < RXBUF_N; i++) {
- + rxbuf.slot[i].buf = dma_pool_alloc(rxbuf.dmapool, GFP_KERNEL,
- + &rxbuf.slot[i].dmabase);
- + if (!rxbuf.slot[i].buf) {
- + pr_err(PRT_NAME
- + ": Error. No enough mem for RXbuf.\n");
- + goto err_alloc_rx_buf;
- + }
- + }
- +
- + felica_rxbuf_clear();
- +
- + return 0;
- +
- +err_alloc_rx_buf:
- + for (i--; i >= 0; i--) {
- + dma_pool_free(rxbuf.dmapool, rxbuf.slot[i].buf,
- + rxbuf.slot[i].dmabase);
- + }
- + dma_pool_destroy(rxbuf.dmapool);
- + rxbuf.dmapool = NULL;
- + return -ENOMEM;
- +}
- +
- +/**
- + * @brief Release RX buffer
- + * @details This function executes;\n
- + * # Release RX buffer\n
- + * # Destroy DMA pool
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_rxbuf_exit(void)
- +{
- + int i;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + for (i = 0; i < RXBUF_N; i++) {
- + dma_pool_free(rxbuf.dmapool, rxbuf.slot[i].buf,
- + rxbuf.slot[i].dmabase);
- + }
- + dma_pool_destroy(rxbuf.dmapool);
- + rxbuf.dmapool = NULL;
- +}
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rxbuf.h b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rxbuf.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_rxbuf.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_rxbuf.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,33 @@
- +/* vendor/semc/hardware/felica/felica_rxbuf.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _FELICA_RXBUF_H
- +#define _FELICA_RXBUF_H
- +
- +#define RXBUF_M 272
- +#define RXBUF_N 128
- +
- +#define DMAPOOL_NAME "felica_rxbuf"
- +#define DMAPOOL_SIZE RXBUF_M
- +/* DMAPOOL_ALIGN must be ">=DMAPOOL_SIZE" and pow of 2 */
- +#define DMAPOOL_ALIGN 512
- +
- +int felica_rxbuf_init(void);
- +void felica_rxbuf_exit(void);
- +void felica_rxbuf_clear(void);
- +int felica_rxbuf_count(void);
- +int felica_rxbuf_gets(char __user *, int);
- +dma_addr_t felica_rxbuf_push_pointer(void);
- +int felica_rxbuf_push_length(void);
- +int felica_rxbuf_push_status_update(int);
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_statemachine.c b/4.1.B.0.479//vendor/semc/hardware/felica/felica_statemachine.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_statemachine.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_statemachine.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,183 @@
- +/* vendor/semc/hardware/felica/felica_statemachine.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/stddef.h>
- +#include <linux/semaphore.h>
- +#include "felica_statemachine.h"
- +#include "felica_statemachine_userdata.h"
- +
- +#define PRT_NAME "flc_statemachine"
- +#define BEFORE_INIT (-1)
- +#define INIT_STATE (0)
- +#define NO_EVENT_REQ (-1)
- +
- +static int state = BEFORE_INIT;
- +static struct event_struct next_evset;
- +static struct semaphore sem_transition;
- +
- +/**
- + * @brief Request next event during action
- + * @param evset : Requested event and its data
- + * @retval 0 : Success.
- + * @note
- + */
- +int felica_request_nextevent(struct event_struct evset)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + next_evset = evset;
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Core of State-machine event handler
- + * @details This function executes;\n
- + * # Check the event number\n
- + * # Check the state number\n
- + * # Init request of next event\n
- + * # Dispatch event according to state\n
- + * # Execute the corresponding function\n
- + * # [If action succeeded,] go to the next state\n
- + * # [If action succeeded and the next event is requested,]
- + * # call this event handler recursively.\n
- + * # Return result
- + * @param evset : Requested event and its data
- + * @retval .retval : Return value of the last action\n
- + * 0/Positive : Action succeeded.\n
- + * Negative : Action failed.\n
- + * STATEMACHINE_ERROR(<0) = Statemachine handling error\n
- + * Others = Failure during the action is executed.
- + * @retval .ev : Event during the last action
- + * @retval .state : State during the last action
- + * @note
- + */
- +static struct result_struct __felica_event_handle(struct event_struct evset)
- +{
- + struct result_struct result;
- + struct transition_struct *t;
- +
- + pr_debug(PRT_NAME ": %s (ev#%d/st#%d)\n", __func__, evset.ev, state);
- +
- + result.ev = evset.ev;
- + result.state = state;
- +
- + /* Check the event number */
- + if ((0 > evset.ev) || (__end_of_event <= evset.ev)) {
- + pr_err(PRT_NAME ": Error. Invalid Event number.\n");
- + result.retval = STATEMACHINE_ERROR;
- + return result;
- + }
- +
- + /* Check the state number */
- + if ((0 > state) || (__end_of_state <= state)) {
- + pr_err(PRT_NAME ": Error. Invalid State number.\n");
- + result.retval = STATEMACHINE_ERROR;
- + return result;
- + }
- +
- + /* Init next event */
- + next_evset.ev = NO_EVENT_REQ;
- + next_evset.evdata = NULL;
- +
- + /* Dispatch event-state */
- + t = &tran[state][evset.ev];
- + if ((NULL == t->action) ||
- + (0 > t->nextstate) || (__end_of_state <= t->nextstate)) {
- + pr_err(PRT_NAME ": Error. Invalid transition defined.\n");
- + result.retval = STATEMACHINE_ERROR;
- + return result;
- + }
- +
- + /* Execute action */
- + result.retval = (t->action)(evset.evdata);
- +
- + if (0 > result.retval)
- + return result;
- +
- + /* Change state */
- + pr_debug(PRT_NAME ": State change #%d -> #%d\n",
- + state, t->nextstate);
- + state = t->nextstate;
- +
- + /* Execute next event recursively, if exists. */
- + if (NO_EVENT_REQ != next_evset.ev)
- + result = __felica_event_handle(next_evset);
- +
- + return result;
- +}
- +
- +/**
- + * @brief State-machine event handler
- + * @details This function executes;\n
- + * # Down semaphore\n
- + * # Call __felica_event_handle\n
- + * # Up semaphore
- + * # Return result
- + * @param evset : Requested event and its data
- + * @retval .retval : Return value of the last action\n
- + * @retval .ev : Event of the last action
- + * @retval .state : State of the last action
- + * @note
- + */
- +struct result_struct felica_event_handle(struct event_struct evset)
- +{
- + struct result_struct result;
- +
- + pr_debug(PRT_NAME ": %s (ev#%d)\n", __func__, evset.ev);
- +
- + down(&sem_transition);
- +
- + result = __felica_event_handle(evset);
- +
- + up(&sem_transition);
- +
- + return result;
- +}
- +
- +/**
- + * @brief Initialization of statemachine
- + * @details This function executes;\n
- + * # Init the semaphore\n
- + * # Set the state to Default
- + * @param N/A
- + * @retval 0 : Success
- + * @note
- + */
- +int felica_statemachine_init(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Init semaphore */
- + init_MUTEX(&sem_transition);
- +
- + /* Start from the default state */
- + state = INIT_STATE;
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Exit function of statemachine
- + * @details This function executes;\n
- + * # Set the state as Statemachine is not ready
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_statemachine_exit(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + state = BEFORE_INIT;
- +}
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_statemachine.h b/4.1.B.0.479//vendor/semc/hardware/felica/felica_statemachine.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_statemachine.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_statemachine.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,40 @@
- +/* vendor/semc/hardware/felica/felica_statemachine.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _FELICA_STATEMACHINE_H
- +#define _FELICA_STATEMACHINE_H
- +
- +#define STATEMACHINE_ERROR (-100)
- +
- +struct transition_struct {
- + int (*action)(void *data);
- + int nextstate;
- +};
- +
- +struct event_struct {
- + int ev;
- + void *evdata;
- +};
- +
- +struct result_struct {
- + int retval;
- + int ev;
- + int state;
- +};
- +
- +struct result_struct felica_event_handle(struct event_struct);
- +int felica_request_nextevent(struct event_struct);
- +
- +int felica_statemachine_init(void);
- +void felica_statemachine_exit(void);
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_statemachine_userdata.h b/4.1.B.0.479//vendor/semc/hardware/felica/felica_statemachine_userdata.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_statemachine_userdata.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_statemachine_userdata.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,128 @@
- +/* vendor/semc/hardware/felica/felica_statemachine_userdata.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _FELICA_STATEMACHINE_USERDATA_H
- +#define _FELICA_STATEMACHINE_USERDATA_H
- +
- +#include "felica_statemachine.h"
- +
- +/* Enumration of State */
- +enum states {
- + uart_closed,
- + uart_open_idle,
- + uart_open_rx,
- + uart_open_tx,
- + __end_of_state
- +};
- +
- +/* Enumration of Event */
- +enum events {
- + open_syscall,
- + close_syscall,
- + read_syscall,
- + available_syscall,
- + write_syscall,
- + fsync_syscall,
- + exec_close_sig,
- + exec_fsync_sig,
- + receive_1byte_sig,
- + rx_complete_sig,
- + rx_to_idle_sig,
- + tx_complete_sig,
- + fsync_timeout_sig,
- + uartdm_error_sig,
- + __end_of_event
- +};
- +
- +int felica_do_open_seq(void *);
- +int felica_do_open_again(void *);
- +int felica_do_close_check(void *);
- +int felica_do_close_seq(void *);
- +int felica_do_read_seq(void *);
- +int felica_do_available_seq(void *);
- +int felica_do_write_seq(void *);
- +int felica_do_fsync_check(void *);
- +int felica_do_fsync_reserve(void *);
- +int felica_do_fsync_cancel(void *);
- +int felica_do_rx_start(void *);
- +int felica_do_rx_finish(void *);
- +int felica_do_rx_reset(void *);
- +int felica_do_tx_start(void *);
- +int felica_do_tx_finish(void *);
- +int felica_do_tx_reset(void *);
- +int felica_do_rx_to_idle(void *);
- +int felica_do_nothing(void *);
- +
- +static struct transition_struct tran[__end_of_state][__end_of_event] = {
- + /* Transitions @ UART CLOSED state*/
- + { {felica_do_open_seq, uart_open_idle},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed},
- + {felica_do_nothing, uart_closed} },
- + /* Transitions @ UART OPEN IDLE state*/
- + { {felica_do_open_again, uart_open_idle},
- + {felica_do_close_check, uart_open_idle},
- + {felica_do_read_seq, uart_open_idle},
- + {felica_do_available_seq, uart_open_idle},
- + {felica_do_write_seq, uart_open_idle},
- + {felica_do_fsync_check, uart_open_idle},
- + {felica_do_close_seq, uart_closed},
- + {felica_do_tx_start, uart_open_tx},
- + {felica_do_rx_start, uart_open_rx},
- + {felica_do_nothing, uart_open_idle},
- + {felica_do_nothing, uart_open_idle},
- + {felica_do_nothing, uart_open_idle},
- + {felica_do_nothing, uart_open_idle},
- + {felica_do_nothing, uart_open_idle} },
- + /* Transitions @ UART OPEN RX state*/
- + { {felica_do_open_again, uart_open_rx},
- + {felica_do_close_check, uart_open_rx},
- + {felica_do_read_seq, uart_open_rx},
- + {felica_do_available_seq, uart_open_rx},
- + {felica_do_write_seq, uart_open_rx},
- + {felica_do_fsync_reserve, uart_open_rx},
- + {felica_do_close_seq, uart_closed},
- + {felica_do_tx_start, uart_open_tx},
- + {felica_do_rx_start, uart_open_rx},
- + {felica_do_rx_finish, uart_open_rx},
- + {felica_do_rx_to_idle, uart_open_idle},
- + {felica_do_nothing, uart_open_rx},
- + {felica_do_fsync_cancel, uart_open_rx},
- + {felica_do_rx_reset, uart_open_rx} },
- + /* Transitions @ UART OPEN TX state*/
- + { {felica_do_open_again, uart_open_tx},
- + {felica_do_close_check, uart_open_tx},
- + {felica_do_read_seq, uart_open_tx},
- + {felica_do_available_seq, uart_open_tx},
- + {felica_do_nothing, uart_open_tx},
- + {felica_do_nothing, uart_open_tx},
- + {felica_do_close_seq, uart_closed},
- + {felica_do_nothing, uart_open_tx},
- + {felica_do_nothing, uart_open_tx},
- + {felica_do_nothing, uart_open_tx},
- + {felica_do_nothing, uart_open_tx},
- + {felica_do_tx_finish, uart_open_idle},
- + {felica_do_tx_reset, uart_open_idle},
- + {felica_do_tx_reset, uart_open_idle} }
- +};
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_txbuf.c b/4.1.B.0.479//vendor/semc/hardware/felica/felica_txbuf.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_txbuf.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_txbuf.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,218 @@
- +/* vendor/semc/hardware/felica/felica_txbuf.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/types.h>
- +#include <linux/stddef.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/uaccess.h>
- +#include "felica_txbuf.h"
- +
- +#define PRT_NAME "txbuf"
- +
- +/* DEBUG_TXBUF_DUMP : 0 = without dump, 1 = with dump */
- +#define DEBUG_TXBUF_DUMP 0
- +
- +struct txbuf_all {
- + int ptr;
- + int num;
- + char *buf;
- + dma_addr_t dmabase;
- +};
- +
- +static struct txbuf_all txbuf;
- +
- +
- +/**
- + * @brief Clear TX buffer
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_txbuf_clear(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + txbuf.num = 0;
- + txbuf.ptr = 0;
- +}
- +
- +/**
- + * @brief Count the number of the stored data in TX buffer
- + * @param N/A
- + * @retval 0/Positive : the number of the stored data
- + * @retval Negative : Failure\n
- + * -ENODEV = TX buf not initialized
- + * @note
- + */
- +int felica_txbuf_count(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (!txbuf.buf) {
- + pr_err(PRT_NAME ": Error. TX buf not initialized.\n");
- + return -ENODEV;
- + }
- +
- + return txbuf.num - txbuf.ptr;
- +}
- +
- +/**
- + * @brief Copy user space data to the TX buffer
- + * @param buf : Pointer to User space buffer
- + * @param len : Date length to copy
- + * @retval Positive : Number of the data copied successfully.
- + * @retval Negative : Failure\n
- + * -EINVAL = Invalid arguments\n
- + * -ENODEV = TX buf not initialized
- + * -EFBIG = Data is too big\n
- + * -EFAULT = Data copy error
- + * @note
- + */
- +int felica_txbuf_puts(const char __user *buf, int len)
- +{
- + int ret;
- + int rest;
- +
- +#if DEBUG_TXBUF_DUMP
- + int i;
- +#endif
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (0 >= len || !buf) {
- + pr_err(PRT_NAME ": Error. Invalid argument.\n");
- + return -EINVAL;
- + }
- + if (!txbuf.buf) {
- + pr_err(PRT_NAME ": Error. TX buf not initialized.\n");
- + return -ENODEV;
- + }
- +
- + rest = TXBUF_SIZE - txbuf.num;
- +
- + if (len > rest) {
- + pr_err(PRT_NAME ": Error. Too many data to write.\n");
- + return -EFBIG;
- + }
- +
- + ret = copy_from_user(txbuf.buf + txbuf.num, buf, len);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. copy_from_user failure.\n");
- + return -EFAULT;
- + }
- +
- +#if DEBUG_TXBUF_DUMP
- + printk("TXputs dump: ");
- + for (i = 0; i < len; i++)
- + printk("%02x ", txbuf.buf[txbuf.num + i]);
- + printk("\n");
- +#endif
- +
- + txbuf.num += len;
- +
- + return len;
- +}
- +
- +/**
- + * @brief Return DMA address pointer to pull data
- + * @param N/A
- + * @retval Valid-address : DMA address to pull
- + * @retval 0 : No space to pull
- + * @note
- + */
- +dma_addr_t felica_txbuf_pull_pointer(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (txbuf.ptr == txbuf.num)
- + return 0;
- +
- + return txbuf.dmabase + txbuf.ptr;
- +}
- +
- +/**
- + * @brief Update TX buffer status according to the pushed data.
- + * @param len : Data length already pushed
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -EINVAL = Invalid argument\n
- + * -ENODEV = TX buf not initialized
- + * @note
- + */
- +int felica_txbuf_pull_status_update(int len)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (0 >= len || TXBUF_SIZE < len) {
- + pr_err(PRT_NAME ": Error. Invalid arg for pull status.\n");
- + return -EINVAL;
- + }
- + if (!txbuf.buf) {
- + pr_err(PRT_NAME ": Error. TX buf not initialized.\n");
- + return -ENODEV;
- + }
- +
- + if (txbuf.ptr + len > txbuf.num) {
- + pr_err(PRT_NAME ": Error. Invalid arg, ptr overtakes num.\n");
- + return -EINVAL;
- + }
- + txbuf.ptr += len;
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Initialize & alloc TX buffer
- + * @details This function executes;\n
- + * # Alloc TX buffer\n
- + * # Call TX buffer clear
- + * @param N/A
- + * @retval 0 : Success
- + * @retval -ENOMEM : Error, no enough memory.
- + * @note
- + */
- +int felica_txbuf_init(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + txbuf.buf = dma_alloc_coherent(NULL, sizeof(char) * TXBUF_SIZE,
- + &txbuf.dmabase, GFP_KERNEL);
- + if (!txbuf.buf) {
- + pr_err(PRT_NAME ": Error. No enough mem for TXbuf.\n");
- + return -ENOMEM;
- + }
- +
- + felica_txbuf_clear();
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Release TX buffer
- + * @details This function executes;\n
- + * # Release TX buffer
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_txbuf_exit(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + dma_free_coherent(NULL, sizeof(char) * TXBUF_SIZE,
- + txbuf.buf, txbuf.dmabase);
- + txbuf.buf = NULL;
- +}
- +
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_txbuf.h b/4.1.B.0.479//vendor/semc/hardware/felica/felica_txbuf.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_txbuf.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_txbuf.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,26 @@
- +/* vendor/semc/hardware/felica/felica_txbuf.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _FELICA_TXBUF_H
- +#define _FELICA_TXBUF_H
- +
- +#define TXBUF_SIZE 260
- +
- +int felica_txbuf_init(void);
- +void felica_txbuf_exit(void);
- +int felica_txbuf_count(void);
- +void felica_txbuf_clear(void);
- +int felica_txbuf_puts(const char __user *, int);
- +dma_addr_t felica_txbuf_pull_pointer(void);
- +int felica_txbuf_pull_status_update(int);
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_uart.c b/4.1.B.0.479//vendor/semc/hardware/felica/felica_uart.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_uart.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_uart.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,1118 @@
- +/* vendor/semc/hardware/felica/felica_uart.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/types.h>
- +#include <linux/stddef.h>
- +#include <linux/fs.h>
- +#include <linux/miscdevice.h>
- +#include <linux/mfd/pmic8058.h>
- +#include <linux/uaccess.h>
- +#include <linux/gpio.h>
- +#include <linux/delay.h>
- +#include "semc_felica_ext.h"
- +#include "felica_uart.h"
- +#include "msm_uartdm.h"
- +#include "msm_uartmux.h"
- +#include "felica_rxbuf.h"
- +#include "felica_txbuf.h"
- +#include "felica_statemachine.h"
- +#include "felica_statemachine_userdata.h"
- +
- +#define PRT_NAME "felica uart"
- +
- +struct felica_uart_data {
- + struct felica_uart_pfdata *pfdata;
- + /* Reference count of FeliCa UART */
- + int refcnt;
- + /* TX reservation during RX */
- + enum {no, yes} tx_reserved;
- + /* Waitquese variables for fsync */
- + wait_queue_head_t wait_fsync;
- + int condition_fsync;
- + /* Result of fsync */
- + enum {success, error} result_fsync;
- + /* Previous available result */
- + int prev_avail;
- +};
- +
- +static struct felica_uart_data *fluart;
- +
- +
- +/**
- + * @brief Action to do nothing
- + * @param nodata : (unused)
- + * @retval 0
- + * @note
- + */
- +int felica_do_nothing(void *nodata)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Execute OPEN sequence of FeliCa UART, after checking UART MUX state
- + * @details This function executes;\n
- + * # Check UART MUX\n
- + * # Set UART MUX for FeliCa\n
- + * # Call UARTDM open function\n
- + * # Clear tx_reserved variable\n
- + * # Call UART 1byte-reception enable function\n
- + * # Increment the reference count to 1
- + * @param nodata : (unused)
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -EBUSY = The UART is occupied by another\n
- + * -EIO = UART MUX access error / UARTDM open error /
- + * Cannot enable 1byte-reception
- + * @note
- + */
- +int felica_do_open_seq(void *nodata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check UART MUX state*/
- + ret = msm_uartmux_get();
- + if (0 > ret) {
- + pr_err(PRT_NAME ": Error. Cannot get UART MUX.\n");
- + ret = -EIO;
- + goto err_uartmux_get;
- + } else if (ret != fluart->pfdata->uartmux_neutral) {
- + pr_err(PRT_NAME ": Error. UART MUX not available.\n");
- + ret = -EBUSY;
- + goto err_uartmux_get;
- + }
- +
- + /* Set UART MUX for FeliCa */
- + ret = msm_uartmux_set(fluart->pfdata->uartmux_felica);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot set UART MUX.\n");
- + ret = -EIO;
- + goto err_uartmux_set;
- + }
- +
- + /* Call UARTDM open function */
- + ret = msm_uartdm_open();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. UART Open failed.\n");
- + ret = -EIO;
- + goto err_uartdm_open;
- + }
- +
- + /* Clear tx_reserved variable */
- + fluart->tx_reserved = no;
- +
- + /* Call UART 1byte-reception enable function */
- + ret = msm_uartdm_rcv_1byte_enable();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot enable RCV.\n");
- + ret = -EIO;
- + goto err_uartdm_rcv_1byte_enable;
- + }
- +
- + /* Increment the reference count to 1 */
- + fluart->refcnt = 1;
- +
- + return 0;
- +
- +err_uartdm_rcv_1byte_enable:
- + msm_uartdm_close();
- +err_uartdm_open:
- + msm_uartmux_set(fluart->pfdata->uartmux_neutral);
- +err_uartmux_set:
- +err_uartmux_get:
- + return ret;
- +}
- +
- +/**
- + * @brief Execute Open again
- + * @details This function executes;\n
- + * # Increment the reference count to 2
- + * @param nodata : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +int felica_do_open_again(void *nodata)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + fluart->refcnt = 2;
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Check if UART can be closed. Issue EXEC_CLOSE_SIG if possible.
- + * @details This function executes;\n
- + * # Decrement the reference count\n
- + * # If it becomes 0 or less, request EXEC_CLOSE_SIG event.
- + * @param nodata : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +int felica_do_close_check(void *nodata)
- +{
- + struct event_struct evset = {exec_close_sig, NULL};
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + fluart->refcnt--;
- + if (0 >= fluart->refcnt)
- + felica_request_nextevent(evset);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Execute Close sequence of FeliCa UART port.
- + * @details This function executes;\n
- + * # Call UART 1byte-reception disable function\n
- + * # Call UARTDM close function\n
- + * # Set UART MUX to Neutral
- + * @param nodata : (unused)
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -EIO = Cannot disable 1byte-reception / UARTDM close error /
- + * UART MUX write error
- + * @note
- + */
- +int felica_do_close_seq(void *nodata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + ret = msm_uartdm_rcv_1byte_disable();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot disable RCV.\n");
- + ret = -EIO;
- + goto err_uartdm_rcv_disable;
- + }
- +
- + ret = msm_uartdm_close();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. UARTDM close failed.\n");
- + ret = -EIO;
- + goto err_uartdm_close;
- + }
- +
- + ret = msm_uartmux_set(fluart->pfdata->uartmux_neutral);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot set UART MUX.\n");
- + ret = -EIO;
- + goto err_uartmux_set;
- + }
- +
- + return 0;
- +
- +err_uartdm_rcv_disable:
- + msm_uartdm_close();
- +err_uartdm_close:
- + msm_uartmux_set(fluart->pfdata->uartmux_neutral);
- +err_uartmux_set:
- + return ret;
- +}
- +
- +/**
- + * @brief Execute Read sequence of FeliCa UART port.
- + * @details This function executes;\n
- + * # Check data length in RX buffer\n
- + * # If data exists, get char data from RX buffer
- + * @param data : Data structure for Read\n
- + * .buf : Pointer to User space\n
- + * .count : Length to read
- + * @retval Positive : Success. Length of the data read successfully
- + * @retval 0 : Success. No data to read
- + * @retval Negative : Failure\n
- + * @retval -EINVAL = The arguments are invalid.\n
- + * @retval -EFAULT = Data cannot be copied from RX buffer.
- + * @note
- + */
- +int felica_do_read_seq(void *data)
- +{
- + int ret;
- + struct read_data_struct *dataset = data;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (!dataset->buf || !dataset->count) {
- + pr_err(PRT_NAME ": Error. Invalid arg @read.");
- + return -EINVAL;
- + }
- +
- + ret = felica_rxbuf_count();
- + if (0 > ret) {
- + pr_err(PRT_NAME ": Error. RXbuf check failed.");
- + return -EFAULT;
- + }
- +
- + if (0 < ret) {
- + ret = felica_rxbuf_gets(dataset->buf, dataset->count);
- + if (0 > ret) {
- + pr_err(PRT_NAME ": Error. RXbuf access failed.");
- + ret = -EFAULT;
- + }
- + }
- +
- + return ret;
- +}
- +
- +/**
- + * @brief Execute Available sequence of FeliCa UART port.
- + * @details This function executes;\n
- + * # Check data length in RX buffer
- + * @param nodata : (unused)
- + * @retval 0/Positive : Success. Length of data stored in RX buffer
- + * @retval Negative : Failure\n
- + * -EFAULT = RX buffer access failed.
- + * @note
- + */
- +int felica_do_available_seq(void *nodata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + ret = felica_rxbuf_count();
- + if (0 > ret) {
- + pr_err(PRT_NAME ": Error. RXbuf check failed.");
- + return -EFAULT;
- + }
- +
- + return ret;
- +}
- +
- +/**
- + * @brief Execute Write sequence of FeliCa UART port.
- + * @details This function executes;\n
- + * # Put char data to TX buffer
- + * @param data : Data structure for Write\n
- + * .buf : Pointer to User space\n
- + * .count : Length to write
- + * @retval Positive : Success. Length of the data written successfully
- + * @retval Negative : Failure\n
- + * -EINVAL = The arguments are invalid.\n
- + * -EFAULT = Data cannot be copied to TX buffer.
- + * @note
- + */
- +int felica_do_write_seq(void *data)
- +{
- + int ret;
- + struct write_data_struct *dataset = data;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (!dataset->buf || !dataset->count) {
- + pr_err(PRT_NAME ": Error. Invalid arg @write.");
- + return -EINVAL;
- + }
- +
- + ret = felica_txbuf_puts(dataset->buf, dataset->count);
- + if (0 > ret) {
- + pr_err(PRT_NAME ": Error. TXbuf access failed.");
- + return -EFAULT;
- + }
- +
- + return ret;
- +}
- +
- +/**
- + * @brief Check if fsync should be executed. Issue EXE_FSYNC_SIG if necessary.
- + * @details This function executes;\n
- + * # Count TX buffer\n
- + * # [If TX data exists,] request EXEC_FSYNC_SIG.
- + * @param nodata : (unused)
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -ENODATA = No data for fsync.\n
- + * -EFAULT = TX buffer check failed.
- + * @note
- + */
- +int felica_do_fsync_check(void *nodata)
- +{
- + int ret;
- + struct event_struct evset = {exec_fsync_sig, NULL};
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + ret = felica_txbuf_count();
- + if (0 > ret) {
- + pr_err(PRT_NAME ": Error. TXbuf check failed.");
- + return -EFAULT;
- + } else if (0 == ret) {
- + pr_debug(PRT_NAME ": No data to do fsync.");
- + return -ENODATA;
- + }
- + felica_request_nextevent(evset);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Check if fsync should be executed, and reserve fsync if necessary.
- + * @details This function executes;\n
- + * # Count TX buffer\n
- + * # [If TX data exists,] set tx_reserved variable as reserved.
- + * @param nodata : (unused)
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -EFAULT = TX buffer access failed.\n
- + * -ENODATA = No data for fsync.
- + * @note
- + */
- +int felica_do_fsync_reserve(void *nodata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + ret = felica_txbuf_count();
- + if (0 > ret) {
- + pr_err(PRT_NAME ": Error. TXbuf check failed.");
- + return -EFAULT;
- + } else if (0 == ret) {
- + pr_debug(PRT_NAME ": No data to do fsync.");
- + return -ENODATA;
- + }
- +
- + fluart->tx_reserved = yes;
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Cancel reserved fsync.
- + * @details This function executes;\n
- + * # Set tx_reserved variable as not-reserved.
- + * @param nodata : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +int felica_do_fsync_cancel(void *nodata)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + fluart->tx_reserved = no;
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Start UARTDM RX transfer
- + * @details This function executes;\n
- + * # Call UARTDM RX start function\n
- + * # If RX start failed, call UARTDM RX reset function.\n
- + * # If RX start failed, enable RX 1byte reception interrupt.
- + * @param nodata : (unused)
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -EIO = UART RX start failed
- + * @note
- + */
- +int felica_do_rx_start(void *nodata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + ret = msm_uartdm_rx_start();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. UART RX start failed.");
- + msm_uartdm_rx_reset();
- + msm_uartdm_rcv_1byte_enable();
- + return -EIO;
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Execute finish sequence of UARTDM RX
- + * @details This function executes;\n
- + * # Check UARTDM received byte\n
- + * # [If additional data exists,] request RECEIVE_1BYTE_SIG event.\n
- + * # [If no data but TX reserved,] request EXEC_FSYNC_SIG event.\n
- + * # [If else,] request RX_TO_IDLE_SIG event.
- + * @param nodata : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +int felica_do_rx_finish(void *nodata)
- +{
- + int ret;
- + struct event_struct evset = {receive_1byte_sig, NULL};
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + ret = msm_uartdm_rcv_byte_check();
- + if (0 == ret) {
- + if (yes == fluart->tx_reserved)
- + evset.ev = exec_fsync_sig;
- + else
- + evset.ev = rx_to_idle_sig;
- + }
- + felica_request_nextevent(evset);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Reset UARTDM RX port
- + * @details This function executes;\n
- + * # Call UARTDM RX reset function\n
- + * # Request RX_COMPLETE_SIG event.
- + * @param nodata : (unused)
- + * @retval 0 : Success.
- + * @retval Negative : Failure\n
- + * -EIO = UARTDM RX reset failed
- + * @note
- + */
- +int felica_do_rx_reset(void *nodata)
- +{
- + int ret;
- + struct event_struct evset = {rx_complete_sig, NULL};
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + ret = msm_uartdm_rx_reset();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. UARTDM RX reset failed.");
- + return -EIO;
- + }
- +
- + felica_request_nextevent(evset);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Start UARTDM TX transfer
- + * @details This function executes;\n
- + * # Set tx_reserved variable as not reserved.\n
- + * # Disable RX 1byte reception interrupt\n
- + * # Call UARTDM TX start function.
- + * @param nodata : (unused)
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -EIO = Cannot disable 1byte-reception / UARTDM TX start failed
- + * @note
- + */
- +int felica_do_tx_start(void *nodata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + fluart->tx_reserved = no;
- +
- + ret = msm_uartdm_rcv_1byte_disable();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot disable RCV.\n");
- + return -EIO;
- + }
- +
- + ret = msm_uartdm_tx_start();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. UARTDM TX start failed.");
- + return -EIO;
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Execute finish sequence of UARTDM TX
- + * @details This function executes;\n
- + * # Clear TX buffer\n
- + * # Enable RX 1byte reception interrupt
- + * @param nodata : (unused)
- + * @retval 0 : Success.
- + * @retval Negative : Failure\n
- + * -EIO = Cannot enable 1byte-reception
- + * @note
- + */
- +int felica_do_tx_finish(void *nodata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + felica_txbuf_clear();
- +
- + ret = msm_uartdm_rcv_1byte_enable();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot enable RCV.\n");
- + return -EIO;
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Reset UARTDM TX port
- + * @details This function executes;\n
- + * # Call UARTDM TX reset\n
- + * # Enable RX 1byte reception interrupt
- + * @param nodata : (unused)
- + * @retval 0 : Success.
- + * @retval Negative : Failure\n
- + * -EIO = UARTDM TX reset failed / Cannot enable 1byte-reception
- + * @note
- + */
- +int felica_do_tx_reset(void *nodata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + ret = msm_uartdm_tx_reset();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. UARTDM TX reset failed.");
- + return -EIO;
- + }
- +
- + ret = msm_uartdm_rcv_1byte_enable();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot enable RCV.\n");
- + return -EIO;
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Return from RX state to IDLE state
- + * @details This function executes;\n
- + * # Enable RX 1byte reception interrupt
- + * @param nodata : (unused)
- + * @retval 0 : Success.
- + * @retval Negative : Failure\n
- + * -EIO = Cannot enable 1byte-reception
- + * @note
- + * @note
- + */
- +int felica_do_rx_to_idle(void *nodata)
- +{
- + int ret;
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + ret = msm_uartdm_rcv_1byte_enable();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot enable RCV.\n");
- + return -EIO;
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Handling RX 1byte reception callback
- + * @details This function executes;\n
- + * # Issue RECEIVE_1BYTE_SIG event
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_cb_rcv_1byte(void)
- +{
- + struct event_struct evset = {receive_1byte_sig, NULL};
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + felica_event_handle(evset);
- +}
- +
- +/**
- + * @brief Handling RX complete callback
- + * @details This function executes;\n
- + * # Issue RX_COMPLETE_SIG event
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_cb_rx_complete(void)
- +{
- + struct event_struct evset = {rx_complete_sig, NULL};
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + felica_event_handle(evset);
- +}
- +
- +/**
- + * @brief Handling RX error callback
- + * @details This function executes;\n
- + * # Issue UARTDM_ERROR_SIG event
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_cb_rx_error(void)
- +{
- + struct event_struct evset = {uartdm_error_sig, NULL};
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + felica_event_handle(evset);
- +}
- +
- +/**
- + * @brief Handling TX complete callback
- + * @details This function executes;\n
- + * # Issue TX_COMPLETE_SIG event\n
- + * # Set result_fsync variable as success\n
- + * # Wakeup FSYNC wait
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_cb_tx_complete(void)
- +{
- + struct event_struct evset = {tx_complete_sig, NULL};
- + struct result_struct result;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + result = felica_event_handle(evset);
- +
- + fluart->result_fsync = success;
- +
- + fluart->condition_fsync = 1;
- + wake_up(&fluart->wait_fsync);
- +}
- +
- +/**
- + * @brief Handling TX error callback
- + * @details This function executes;\n
- + * # Issue UARTDM_ERROR_SIG event\n
- + * # Set result_fsync variable as error\n
- + * # Wakeup FSYNC wait
- + * @param N/A
- + * @retval N/A
- + */
- +void felica_cb_tx_error(void)
- +{
- + struct event_struct evset = {uartdm_error_sig, NULL};
- + struct result_struct result;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + result = felica_event_handle(evset);
- +
- + fluart->result_fsync = error;
- +
- + fluart->condition_fsync = 1;
- + wake_up(&fluart->wait_fsync);
- +}
- +
- +/**
- + * @brief Handle OPEN system call of FeliCa UART
- + * @details This function executes;\n
- + * # Issue OPEN_SYSCALL event
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -EIO = Action failed.
- + */
- +static int felica_uart_open(struct inode *inode, struct file *file)
- +{
- + struct event_struct evset = {open_syscall, NULL};
- + struct result_struct result;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + result = felica_event_handle(evset);
- +
- + fluart->prev_avail = 0;
- +
- + if (0 > result.retval)
- + return -EIO;
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Handle CLOSE system call of FeliCa UART
- + * @details This function executes;\n
- + * # Issue CLOSE_SYSCALL event
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval Negative : Failure\n
- + * -EIO = Action failed.
- + */
- +static int felica_uart_release(struct inode *inode, struct file *file)
- +{
- + struct event_struct evset = {close_syscall, NULL};
- + struct result_struct result;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + result = felica_event_handle(evset);
- +
- + if (0 > result.retval)
- + return -EIO;
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Handle READ system call of FeliCa UART
- + * @details This function executes;\n
- + * # Issue READ_SYSCALL event\n
- + * # [Optional][If no data,] sleep
- + * @param file : (unused)
- + * @param buf : Destination of the read data
- + * @param count : Data length to read
- + * @param offset : (unused)
- + * @retval Positive : Success. Length of possibly read data
- + * @retval 0 : Success. No data to read
- + * @retval Negative : Failure\n
- + * -EINVAL = The arguments are invalid.\n
- + * -EIO = Action to read data failed.
- + */
- +static ssize_t felica_uart_read(struct file *file, char __user *buf,
- + size_t count, loff_t *offset)
- +{
- + struct read_data_struct dataset = {buf, count};
- + struct event_struct evset = {read_syscall, (void *) &dataset};
- + struct result_struct result;
- +
- + pr_debug(PRT_NAME ": %s (%d)\n", __func__, count);
- +
- + if (!buf || !count) {
- + pr_err(PRT_NAME ": Error. Invalid arg @read.\n");
- + return -EINVAL;
- + }
- +
- + result = felica_event_handle(evset);
- + pr_debug(PRT_NAME ": Read result = %d.\n", result.retval);
- +
- + /* [Optional][If no data,] sleep */
- + if ((0 == result.retval) && (0 < FELICA_UART_READ_MSLEEP)) {
- + pr_debug(PRT_NAME ": Read sleep(%dms).\n",
- + FELICA_UART_READ_MSLEEP);
- + msleep(FELICA_UART_READ_MSLEEP);
- + }
- +
- + if (0 > result.retval)
- + return -EIO;
- +
- + return result.retval;
- +}
- +
- +/**
- + * @brief Handle WRITE system call of FeliCa UART
- + * @details This function executes;\n
- + * # Issue WRITE_SYSCALL event.
- + * @param file : (unused)
- + * @param buf : Source of the written data
- + * @param count : Data length to write
- + * @param offset : (unused)
- + * @retval Positive : Success. Length of the data written successfully.
- + * @retval Negative : Failure\n
- + * -EINVAL = The arguments are invalid.\n
- + * -EIO = Action to write data failed.
- + */
- +static ssize_t felica_uart_write(struct file *file, const char __user *buf,
- + size_t count, loff_t *offset)
- +{
- + struct write_data_struct dataset = {buf, count};
- + struct event_struct evset = {write_syscall, (void *) &dataset};
- + struct result_struct result;
- +
- + pr_debug(PRT_NAME ": %s (%d)\n", __func__, count);
- +
- + if (!buf || !count) {
- + pr_err(PRT_NAME ": Error. Invalid arg @available.\n");
- + return -EINVAL;
- + }
- +
- + result = felica_event_handle(evset);
- +
- + if (0 > result.retval)
- + return -EIO;
- +
- + return result.retval;
- +}
- +
- +/**
- + * @brief Handle FSYNC system call of FeliCa UART
- + * @details This function executes;\n
- + * # Issue FSYNC_SYSCALL event\n
- + * # [If no TX data exists,] finish successfully.\n
- + * # Wait until TX completes.\n
- + * # [If wait timeout,] issue FSYNC_TIMOUT_SIG.\n
- + * # Check TX result.
- + * @param file : (unused)
- + * @param dentry : (unused)
- + * @param datasync : (unused)
- + * @retval 0 : Success.
- + * @retval Negative : Failure\n
- + * -EFAULT = DMA transfer error occurred.
- + * -EAGAIN = Time out occurs.
- + */
- +static int felica_uart_fsync(struct file *file, struct dentry *dentry,
- + int datasync)
- +{
- + int ret;
- + struct event_struct evset = {fsync_syscall, NULL};
- + struct event_struct evset_to = {fsync_timeout_sig, NULL};
- + struct result_struct result;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + fluart->condition_fsync = 0;
- +
- + result = felica_event_handle(evset);
- +
- + if (-ENODATA == result.retval) {
- + pr_debug(PRT_NAME ": No data to do fsync.\n");
- + return 0;
- + } else if (0 > result.retval) {
- + pr_err(PRT_NAME ": Error. FSYNC error.\n");
- + return -EFAULT;
- + }
- +
- + if (0 == fluart->condition_fsync) {
- + pr_debug(PRT_NAME ": FSYNC waiting ...\n");
- + /* Wait here until TX completes */
- + ret = wait_event_timeout(fluart->wait_fsync,
- + fluart->condition_fsync, FELICA_UART_FSYNC_TIMEOUT);
- + /* Time out case */
- + if (0 == ret) {
- + pr_err(PRT_NAME ": Error. FSYNC timeout.\n");
- + result = felica_event_handle(evset_to);
- + return -EAGAIN;
- + }
- + /* Check fsync result */
- + if (error == fluart->result_fsync) {
- + pr_err(PRT_NAME ": Error. FSYNC error.\n");
- + return -EFAULT;
- + }
- + }
- +
- + pr_debug(PRT_NAME ": FSYNC succeeded.\n");
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Handle IOCTL system call of FeliCa UART
- + * @details This function executes;\n
- + * # Check IO control number is Available (FIONREAD).\n
- + * # Issue AVAIABLE_SYSCALL event.\n
- + * # Copy result to User space\n
- + * # [Optional][If data not increase,] sleep
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @param cmd : IOCTL command number
- + * @param arg : IOCTL arguments
- + * @retval 0 : Success.
- + * @retval Negative : Failure.\n
- + * -EINVAL = The arguments are invalid for Available.\n
- + * -EFAULT = RX buffer/Data copy error to execute Available.\n
- + * -ENOTTY = Unsupported IOCTL number
- + */
- +static int felica_uart_ioctl(struct inode *inode, struct file *file,
- + unsigned int cmd, unsigned long arg)
- +{
- + int ret;
- + struct event_struct evset = {available_syscall, NULL};
- + struct result_struct result;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (IOCTL_UART_AVAILABLE == cmd) {
- + pr_debug(PRT_NAME ": cmd = AVAILABLE\n");
- + if (!arg) {
- + pr_err(PRT_NAME
- + ": Error. Invalid arg @available.\n");
- + return -EINVAL;
- + }
- +
- + result = felica_event_handle(evset);
- + if (0 > result.retval) {
- + pr_err(PRT_NAME ": Error. RX buffer check failed.\n");
- + return -EFAULT;
- + }
- +
- + ret = copy_to_user((int __user *) arg,
- + &result.retval, sizeof(int));
- + if (ret) {
- + pr_err(PRT_NAME
- + ": Error. copy_to_user failed.\n");
- + return -EFAULT;
- + }
- + pr_debug(PRT_NAME ": Availble result = %d.\n", result.retval);
- +
- + /* [Optional][If data not increase,] sleep */
- + if ((result.retval == fluart->prev_avail)
- + && (0 < FELICA_UART_AVAILABLE_MSLEEP)) {
- + pr_debug(PRT_NAME ": Available sleep(%dms).\n",
- + FELICA_UART_AVAILABLE_MSLEEP);
- + msleep(FELICA_UART_AVAILABLE_MSLEEP);
- + }
- + fluart->prev_avail = result.retval;
- +
- + return 0;
- + } else {
- + pr_err(PRT_NAME ": Error. Unsupported IOCTL.\n");
- + return -ENOTTY;
- + }
- +}
- +
- +/***************** UART FOPS ****************************/
- +static const struct file_operations felica_uart_fops = {
- + .owner = THIS_MODULE,
- + .read = felica_uart_read,
- + .write = felica_uart_write,
- + .ioctl = felica_uart_ioctl,
- + .open = felica_uart_open,
- + .release = felica_uart_release,
- + .fsync = felica_uart_fsync,
- +};
- +
- +static struct miscdevice felica_uart_device = {
- + .minor = MISC_DYNAMIC_MINOR,
- + .name = "felica",
- + .fops = &felica_uart_fops,
- +};
- +
- +/**
- + * @brief Initialize FeliCa UART and register its device
- + * @details This function executes;\n
- + * # Check UART platform data\n
- + * # Alloc and Initialize UART controller's data\n
- + * # Call UARTDM module init function\n
- + * # Call UARTMUX module init function\n
- + * # Init UART ref count\n
- + * # Create UART character device (/dev/felica)\n
- + * # State-machine initialization
- + * @param pfdata : Pointer to UART platform data
- + * @retval 0 : Success
- + * @retval Negative : Initialization failed.\n
- + * -EINVAL = No platform data\n
- + * -ENOMEM = No enough memory / Cannot create char dev.\n
- + * -EIO = UARTDM init error.\n
- + * -ENODEV = Transition definition not exists.
- + * @note
- + */
- +int felica_uart_probe_func(struct felica_uart_pfdata *pfdata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check platform data argment */
- + if (!pfdata) {
- + pr_err(PRT_NAME ": Error. No platform data for FeliCa UART.\n");
- + ret = -EINVAL;
- + goto err_check_platform_data;
- + }
- +
- + /* Alloc driver data area */
- + fluart = kzalloc(sizeof(struct felica_uart_data), GFP_KERNEL);
- + if (!fluart) {
- + pr_err(PRT_NAME ": Error. No enough mem for UART.\n");
- + ret = -ENOMEM;
- + goto err_alloc_uart_data;
- + }
- + /* Import UART platform data */
- + fluart->pfdata = pfdata;
- + /* Init wait queue */
- + init_waitqueue_head(&fluart->wait_fsync);
- + /* Set UARTDM callbacks functions */
- + pfdata->uartdm_pfdata.callback_rcv_1byte = felica_cb_rcv_1byte;
- + pfdata->uartdm_pfdata.callback_rx_complete = felica_cb_rx_complete;
- + pfdata->uartdm_pfdata.callback_rx_error = felica_cb_rx_error;
- + pfdata->uartdm_pfdata.callback_tx_complete = felica_cb_tx_complete;
- + pfdata->uartdm_pfdata.callback_tx_error = felica_cb_tx_error;
- +
- + /* UARTDM module init */
- + ret = msm_uartdm_init(&pfdata->uartdm_pfdata);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. UARTDM init failed.\n");
- + ret = -EIO;
- + goto err_msm_uartdm_init;
- + }
- +
- + /* UARTMUX module init */
- + msm_uartmux_init();
- +
- + /* Init UART ref count*/
- + fluart->refcnt = 0;
- +
- + /* Crate UART character device */
- + ret = misc_register(&felica_uart_device);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot register UART.\n");
- + ret = -ENOMEM;
- + goto err_create_uart_dev;
- + }
- +
- + /* State machine initialization */
- + if (NULL == tran[0][0].action) { /* Must refer to tran for build */
- + ret = -ENODEV;
- + goto err_tran_definition;
- + }
- + felica_statemachine_init();
- +
- + return 0;
- +
- +err_tran_definition:
- + misc_deregister(&felica_uart_device);
- +err_create_uart_dev:
- + msm_uartmux_exit();
- + msm_uartdm_exit();
- +err_msm_uartdm_init:
- + kfree(fluart);
- +err_alloc_uart_data:
- +err_check_platform_data:
- + return ret;
- +}
- +
- +/**
- + * @brief Terminate FeliCa UART controller
- + * @details This function executes;\n
- + * # Issue EXEC_CLOSE_SIG for the case UART is opened\n
- + * # State-machine termination\n
- + * # Dedegister UART character device (/dev/felica)\n
- + * # Call UARTMUX module exit function\n
- + * # Call UARTDM module exit function\n
- + * # Release UART controller's data
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_uart_remove_func(void)
- +{
- + struct event_struct evset = {exec_close_sig, NULL};
- + struct result_struct result;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Forced exec_close_sig */
- + result = felica_event_handle(evset);
- +
- + felica_statemachine_exit();
- + misc_deregister(&felica_uart_device);
- + msm_uartmux_exit();
- + msm_uartdm_exit();
- + kfree(fluart);
- +}
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/felica_uart.h b/4.1.B.0.479//vendor/semc/hardware/felica/felica_uart.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/felica_uart.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/felica_uart.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,40 @@
- +/* vendor/semc/hardware/felica/felica_uart.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _FELICA_UART_H
- +#define _FELICA_UART_H
- +
- +#include <linux/param.h>
- +#include <asm/ioctls.h>
- +
- +#define FELICA_UART_FSYNC_TIMEOUT (3 * HZ)
- +#define FELICA_UART_READ_MSLEEP 1
- +#define FELICA_UART_AVAILABLE_MSLEEP 1
- +
- +#define IOCTL_UART_AVAILABLE FIONREAD
- +
- +struct felica_uart_pfdata;
- +
- +struct read_data_struct {
- + char __user *buf;
- + size_t count;
- +};
- +
- +struct write_data_struct {
- + const char __user *buf;
- + size_t count;
- +};
- +
- +int felica_uart_probe_func(struct felica_uart_pfdata *);
- +void felica_uart_remove_func(void);
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/msm_felica_cen.c b/4.1.B.0.479//vendor/semc/hardware/felica/msm_felica_cen.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/msm_felica_cen.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/msm_felica_cen.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,389 @@
- +/* vendor/semc/hardware/felica/msm_felica_cen.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/types.h>
- +#include <linux/stddef.h>
- +#include <linux/fs.h>
- +#include <linux/miscdevice.h>
- +#include <linux/mfd/pmic8058.h>
- +#include <linux/pmic8058-nfc.h>
- +#include <linux/delay.h>
- +#include <linux/uaccess.h>
- +#include "semc_felica_ext.h"
- +#include "felica_cen.h"
- +#include <crypto/hash.h>
- +#include <linux/slab.h>
- +
- +#define PRT_NAME "felica cen"
- +#define MON_LEVEL_IS_2P90 (0x0)
- +#define MON_LEVEL_IS_2P95 (0x1)
- +#define MON_LEVEL_IS_3P00 (0x2)
- +#define MON_LEVEL_IS_3P05 (0x3)
- +#define CEN_LOW (0x00)
- +#define CEN_HIGH (0x01)
- +#define WRITE_LEN 1025
- +#define AUTHENTICATION_LEN (WRITE_LEN - 1)
- +#define AUTH_HASH_LEN 32
- +#define HASH_ALG "sha256"
- +
- +struct felica_cen_data {
- + struct felica_cen_pfdata *pfdata;
- + struct pm8058_nfc_device *nfcdev;
- +};
- +
- +static struct felica_cen_data *flcen;
- +
- +/** @brief Data of sha256 hash digest controller */
- +struct sdesc {
- + struct shash_desc shash;
- + char ctx[];
- +};
- +
- +/** @ Authentication hash value*/
- +const u8 auth_hash[AUTH_HASH_LEN] = {
- + 0xbf, 0x19, 0x2e, 0xaf, 0x67, 0x0c, 0x90, 0xc8,
- + 0x12, 0x5f, 0xbb, 0xbc, 0x9e, 0x17, 0x23, 0x39,
- + 0x69, 0x4a, 0xb7, 0xec, 0x3a, 0x9f, 0x91, 0x57,
- + 0x80, 0xec, 0xb3, 0xf5, 0xfe, 0x28, 0x8f, 0x33
- +};
- +
- +/**
- + * @brief Generation of hash digest in SHA256
- + * @details This function executes;\n
- + * # Generate hash algorithm structure\n
- + * # Generate calculate controller\n
- + * # Calculation of hash digest in SHA256
- + * @param src : Source of hash
- + * @param src_len : Source of length
- + * @param out : Hash digest in SHA256
- + * @retval 0 : Success
- + * @retval -EFAULT : Failure
- + * @note
- + */
- +int calc_hash(const u8 *src, int src_len, u8 *out)
- +{
- + struct crypto_shash *shash;
- + struct sdesc *desc;
- + int size;
- + int ret = -EFAULT;
- +
- + shash = crypto_alloc_shash(HASH_ALG, 0, CRYPTO_ALG_ASYNC);
- + if (IS_ERR(shash)) {
- + pr_err(PRT_NAME ": Error. crypto_alloc_shash.\n");
- + goto err_shash;
- + }
- +
- + size = sizeof(struct shash_desc) + crypto_shash_descsize(shash);
- + desc = kmalloc(size, GFP_KERNEL);
- + if (!desc) {
- + pr_err(PRT_NAME ": Error. No enough mem for Desc.\n");
- + goto err_desc;
- + }
- +
- + desc->shash.tfm = shash;
- + desc->shash.flags = 0x00;
- +
- + if (crypto_shash_digest(&desc->shash, src, src_len, out)) {
- + pr_err(PRT_NAME ": Error. generate hash.\n");
- + goto err_generate;
- + }
- + ret = 0;
- +
- +err_generate:
- + kfree(desc);
- +err_desc:
- + crypto_free_shash(shash);
- +err_shash:
- + return ret;
- +}
- +
- +/**
- + * @brief Open file operation of FeliCa CEN controller
- + * @details This function executes;\n
- + * # Get PMIC8058 NFC device\n
- + * # Read NFC support register\n
- + * # [If NFC support is not enabled,] write initial value.
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -ENODEV = Cannot find PMIC NFC device\n
- + * -EIO = Cannot access PMIC NFC device
- + * @note
- + */
- +static int felica_cen_open(struct inode *inode, struct file *file)
- +{
- + int ret;
- + unsigned int st;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Get PM8058 NFC device */
- + flcen->nfcdev = pm8058_nfc_request();
- + if (NULL == flcen->nfcdev) {
- + pr_err(PRT_NAME ": Error. PM-nfc not found.\n");
- + return -ENODEV;
- + }
- +
- + /* Read NFC support register */
- + ret = pm8058_nfc_get_status(flcen->nfcdev, PM_NFC_CTRL_REQ, &st);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. PM-nfc access failed.\n");
- + return -EIO;
- + }
- + pr_debug(PRT_NAME ": PM8058 NFC register = 0x%x\n", st);
- +
- + /* [If NFC support is not enabled,] write initial value. */
- + if (!(st & PM_NFC_SUPPORT_EN)) {
- + ret = pm8058_nfc_config(flcen->nfcdev, PM_NFC_CTRL_REQ,
- + PM_NFC_SUPPORT_EN | PM_NFC_LDO_EN | MON_LEVEL_IS_2P95);
- + if (ret) {
- + pr_err(PRT_NAME ": Cannot enable PM-nfc.\n");
- + return -EIO;
- + }
- + pr_debug(PRT_NAME ": Successfully enabled PM-nfc.\n");
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Close file operation of FeliCa CEN controller
- + * @param inode : (unused)
- + * @param file : (unused)
- + * @retval 0 : Success
- + * @note
- + */
- +static int felica_cen_release(struct inode *inode, struct file *file)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Read file operation of FeliCa CEN controller
- + * @details This function executes;\n
- + * # Read PMIC8058 NFC support register\n
- + * # Copy PM_NFC_EN value to user space
- + * @param file : (unused)
- + * @param buf : Destination of the read data
- + * @param count : Data length must be 1
- + * @param offset : (unused)
- + * @retval 1 : Success
- + * @retval Negative : Failure\n
- + * -EINVAL = Invalid argment\n
- + * -EIO = Cannot access PMIC NFC device\n
- + * -EFAULT = Cannot copy data to user space
- + * @note
- + */
- +static ssize_t felica_cen_read(struct file *file, char __user *buf,
- + size_t count, loff_t *offset)
- +{
- + int ret;
- + char kbuf;
- + unsigned int st = 0x00000000;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (1 != count || !buf) {
- + pr_err(PRT_NAME ": Error. Invalid arg @CEN read.\n");
- + return -EINVAL;
- + }
- +
- + /* Read PMIC8058 NFC support register */
- + ret = pm8058_nfc_get_status(flcen->nfcdev, PM_NFC_CTRL_REQ, &st);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. PM-nfc access failed.\n");
- + return -EIO;
- + }
- + pr_debug(PRT_NAME ": PM8058 NFC register = 0x%x\n", st);
- + kbuf = (st & PM_NFC_EN) ? CEN_HIGH : CEN_LOW;
- +
- + /* Copy PM_NFC_EN value to user space */
- + ret = copy_to_user(buf, &kbuf, 1);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. copy_to_user failure.\n");
- + return -EFAULT;
- + }
- +
- + /* 1 byte read */
- + return 1;
- +}
- +
- +/**
- + * @brief Write file operation of FeliCa CEN controller
- + * @details This function executes;\n
- + * # Carry out user authentication\n
- + * # Copy value from user space\n
- + * # Write PMIC8058 NFC support register\n
- + * # usec delay
- + * @param file : (unused)
- + * @param buf : Source of the written data
- + * @param count : Data length must be WRITE_LEN.
- + * @param offset : (unused)
- + * @retval 1 : Success
- + * @retval Negative : Failure\n
- + * -EINVAL = Invalid argument\n
- + * -ENOMEM = No enough memory\n
- + * -EFAULT = Cannot copy data from user space\n
- + * -EIO = Cannot access PMIC NFC device\n
- + * -EACCES = Permission denied
- + */
- +static ssize_t felica_cen_write(struct file *file, const char __user *buf,
- + size_t count, loff_t *offset)
- +{
- + int ret;
- + char kbuf;
- + unsigned int val;
- + u8 *src;
- + u8 hash[AUTH_HASH_LEN];
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (WRITE_LEN != count || !buf) {
- + pr_err(PRT_NAME ": Error. Invalid arg @CEN write.\n");
- + return -EINVAL;
- + }
- +
- + /* Carry out user authentication */
- + src = kmalloc(AUTHENTICATION_LEN, GFP_KERNEL);
- + if (!src) {
- + pr_err(PRT_NAME ": Error. No enough mem for Auth.\n");
- + return -ENOMEM;
- + }
- + ret = copy_from_user(src, buf, AUTHENTICATION_LEN);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. copy_from_user failure.\n");
- + kfree(src);
- + return -EFAULT;
- + }
- +
- + if (calc_hash(src, AUTHENTICATION_LEN, hash)) {
- + pr_err(PRT_NAME ": Error. calc hash digest failure.\n");
- + kfree(src);
- + return -EACCES;
- + }
- +
- + if (memcmp(auth_hash, hash, AUTH_HASH_LEN)) {
- + pr_err(PRT_NAME ": Error. invalid authentication.\n");
- + kfree(src);
- + return -EACCES;
- + }
- + kfree(src);
- +
- + /* Copy value from user space */
- + ret = copy_from_user(&kbuf, &buf[AUTHENTICATION_LEN], 1);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. copy_from_user failure.\n");
- + return -EFAULT;
- + }
- +
- + /* Write PMIC8058 NFC support register */
- + if (CEN_LOW == kbuf)
- + val = 0x0;
- + else if (CEN_HIGH == kbuf)
- + val = PM_NFC_EN;
- + else {
- + pr_err(PRT_NAME ": Error. Invalid val @CEN write.\n");
- + return -EINVAL;
- + }
- + ret = pm8058_nfc_config(flcen->nfcdev, PM_NFC_EN, val);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot write PM-nfc.\n");
- + return -EIO;
- + }
- +
- + /* usec delay*/
- + udelay(UDELAY_CEN_WRITE);
- +
- + /* 1 byte write */
- + return 1;
- +}
- +
- +/***************** CEN FOPS ****************************/
- +static const struct file_operations felica_cen_fops = {
- + .owner = THIS_MODULE,
- + .read = felica_cen_read,
- + .write = felica_cen_write,
- + .ioctl = NULL,
- + .open = felica_cen_open,
- + .release = felica_cen_release,
- + .fsync = NULL,
- +};
- +
- +static struct miscdevice felica_cen_device = {
- + .minor = MISC_DYNAMIC_MINOR,
- + .name = "felica_cen",
- + .fops = &felica_cen_fops,
- +};
- +
- +/**
- + * @brief Initialize FeliCa CEN controller
- + * @details This function executes;\n
- + * # Check CEN platform data\n
- + * # Alloc and Initialize CEN controller's data\n
- + * # Create CEN character device (/dev/felica_cen)
- + * @param pfdata : Pointer to CEN platform data
- + * @retval 0 : Success
- + * @retval Negative : Initialization failed.\n
- + * -EINVAL = No platform data\n
- + * -ENOMEM = No enough memory / Cannot create char dev
- + * @note
- + */
- +int felica_cen_probe_func(struct felica_cen_pfdata *pfdata)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check CEN platform data */
- + if (!pfdata) {
- + pr_err(PRT_NAME ": Error. No platform data for CEN.\n");
- + return -EINVAL;
- + }
- +
- + /* Alloc and Initialize CEN controller's data */
- + flcen = kzalloc(sizeof(struct felica_cen_data), GFP_KERNEL);
- + if (!flcen) {
- + pr_err(PRT_NAME ": Error. No enough mem for CEN.\n");
- + return -ENOMEM;
- + }
- + flcen->pfdata = pfdata;
- +
- + /* Create CEN character device (/dev/felica_cen) */
- + if (misc_register(&felica_cen_device)) {
- + pr_err(PRT_NAME ": Error. Cannot register CEN.\n");
- + kfree(flcen);
- + return -ENOMEM;
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Terminate FeliCa cen controller
- + * @details This function executes;\n
- + * # Deregister CEN character device (/dev/felica_cen)\n
- + * # Release CEN controller's data
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void felica_cen_remove_func(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + misc_deregister(&felica_cen_device);
- + kfree(flcen);
- +}
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/msm_uartdm.c b/4.1.B.0.479//vendor/semc/hardware/felica/msm_uartdm.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/msm_uartdm.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/msm_uartdm.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,1009 @@
- +/* vendor/semc/hardware/felica/msm_uartdm.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/stddef.h>
- +#include <linux/err.h>
- +#include <linux/types.h>
- +#include <linux/clk.h>
- +#include <linux/io.h>
- +#include <linux/ioport.h>
- +#include <linux/workqueue.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/interrupt.h>
- +#include <mach/dma.h>
- +#include "semc_felica_ext.h"
- +#include "msm_uartdm.h"
- +#include "msm_uartmux.h"
- +#include "felica_rxbuf.h"
- +#include "felica_txbuf.h"
- +
- +#define PRT_NAME "msm uartdm"
- +#define DMOV_NON_GRACEFUL (0)
- +#define DMOV_GRACEFUL (1)
- +
- +struct msm_uartdm_data {
- + /* Platform data */
- + struct msm_uartdm_pfdata *pfdata;
- + /* Workqueue for callback */
- + struct workqueue_struct *uartdm_wq;
- + struct work_struct rcv_1byte_work;
- + struct work_struct rx_end_work;
- + struct work_struct rx_error_work;
- + struct work_struct tx_end_work;
- + struct work_struct tx_error_work;
- + /* IO-remap of UARTDM port */
- + char *vaddr_uartdm;
- + struct resource *iores_uartdm;
- + /* UARTDM clock */
- + struct clk *clk_uartdm;
- + /* TX DMOV data */
- + struct msm_dmov_cmd txdmov_cmd;
- + dmov_box *txbox;
- + u32 *txbox_ptr;
- + dma_addr_t mapped_txbox;
- + dma_addr_t mapped_txbox_ptr;
- + /* RX DMOV data */
- + struct msm_dmov_cmd rxdmov_cmd;
- + dmov_box *rxbox;
- + u32 *rxbox_ptr;
- + dma_addr_t mapped_rxbox;
- + dma_addr_t mapped_rxbox_ptr;
- + /* Record of IMR registger */
- + unsigned int imr_reg;
- + /* Record of IMR registger */
- + spinlock_t lock;
- + /* Dummy distination for RX discard */
- + void *dummy_dst_buf;
- + dma_addr_t dummy_dst_dmabase;
- +};
- +
- +static struct msm_uartdm_data *urdm;
- +
- +/**
- + * @brief Read function of UARTDM register
- + * @param offset : Offset from UARTDM base address
- + * @retval value : Register value (32bit)
- + * @note If offset is out of range, error message is displayed.
- + * No error returns.
- + */
- +static unsigned int msm_uartdm_read(unsigned int offset)
- +{
- + if (UARTDM_SIZE <= offset) {
- + pr_err(PRT_NAME ": Error. msm_uartdm_read invalid offset\n");
- + return 0x0;
- + }
- + return ioread32(urdm->vaddr_uartdm + offset);
- +}
- +
- +/**
- + * @brief Write function of UARTDM register
- + * @param offset : Offset from UARTDM base address
- + * @param value : Register value to write (32bit)
- + * @retval N/A
- + * @note If offset is out of range, error message is displayed.
- + * No error returns.
- + */
- +static void msm_uartdm_write(unsigned int offset, unsigned int value)
- +{
- + if (UARTDM_SIZE <= offset) {
- + pr_err(PRT_NAME ": Error. msm_uartdm_write invalid offset\n");
- + return;
- + }
- + iowrite32(value, urdm->vaddr_uartdm + offset);
- +}
- +
- +/**
- + * @brief RX DMA completiton handling
- + * @details This function executes;\n
- + * # Disable RX stale interrupt\n
- + * # UARTDM command (Disable stale event)\n
- + * # UARTDM command (Reset stale event)\n
- + * # [If RX DMA succeeded,] queue work of RX end\n
- + * # [If RX DMA failed,] queue work of RX error\n
- + * @param cmd_ptr : (unused)
- + * @param result : Result value of the DMA transfer (32bit data)
- + * @param err : (unused)
- + * @retval N/A
- + * @note
- + */
- +static void msm_uartdm_rxdmov_callback(struct msm_dmov_cmd *cmd_ptr,
- + unsigned int result, struct msm_dmov_errdata *err)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Disable RX Stale interrupt */
- + urdm->imr_reg &= ~BIT_RXSTALE;
- + msm_uartdm_write(UART_DM_IMR, urdm->imr_reg);
- + /* UARTDM command (Disable stale event) */
- + msm_uartdm_write(UART_DM_CR, GCMD_DISABLE_STALE_EVENT);
- + /* UARTDM command (Reset stale event) */
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_STALE_INTERRUPT);
- +
- + if (result & DMOV_RSLT_ERROR)
- + /* Queue work of RX end */
- + queue_work(urdm->uartdm_wq, &urdm->rx_error_work);
- + else
- + /* Queue work of RX error */
- + queue_work(urdm->uartdm_wq, &urdm->rx_end_work);
- +}
- +
- +/**
- + * @brief TX DMOV completiton handling
- + * @details This function executes;\n
- + * # [If TX DMA succeeded,] enable TX ready interrupt.\n
- + * # [If TX DMA failed,] queue work of TX error\n
- + * @param cmd_ptr : (unused)
- + * @param result : Result value of the DMA transfer (32bit data)
- + * @param err : (unused)
- + * @retval N/A
- + */
- +static void msm_uartdm_txdmov_callback(struct msm_dmov_cmd *cmd_ptr,
- + unsigned int result, struct msm_dmov_errdata *err)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (result & DMOV_RSLT_ERROR) {
- + queue_work(urdm->uartdm_wq, &urdm->tx_error_work);
- + } else {
- + urdm->imr_reg |= BIT_TX_READY;
- + msm_uartdm_write(UART_DM_IMR, urdm->imr_reg);
- + }
- +}
- +
- +/**
- + * @brief RX DMOV reset
- + * @details This function executes;\n
- + * # Order RX graceful flush of DMA
- + * @param N/A
- + * @retval N/A
- + * @note If no active RX-DMA command, msm_dmov_flush() does nothing.
- + */
- +static void msm_uartdm_rxdmov_reset(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + msm_dmov_flush(urdm->pfdata->chan_uartdm_rx);
- +}
- +
- +/**
- + * @brief IRQ handler of MSM UARTDM
- + * @details This function executes;\n
- + * [If ISR == RXLEV,]\n
- + * # Disable RXLEV interrupt\n
- + * # Queue work of 1byte reception\n
- + * [If ISR == RX stale,]\n
- + * # Disable RX stale interrupt\n
- + * # Order RX graceful flush of DMA\n
- + * [If ISR == TX ready,]\n
- + * # Disable TX ready interrupt\n
- + * # Reset command of TX ready\n
- + * # Queue work of TX end
- + * @param irq : (unused)
- + * @param dev : (unused)
- + * @retval IRQ_HANDLED : Success. IRQ handled.
- + * @retval IRQ_NONE : Failure. Unknown IRQ reason.
- + * @note
- + */
- +static irqreturn_t msm_uartdm_irq_handler(int irq, void *dev)
- +{
- + unsigned int isr_reg;
- + unsigned long flags;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + spin_lock_irqsave(&urdm->lock, flags);
- +
- + isr_reg = msm_uartdm_read(UART_DM_ISR);
- +
- + pr_debug(PRT_NAME ": IMR = 0x%x, ISR =0x%x\n", urdm->imr_reg, isr_reg);
- +
- + /* RXLEV (1byte recognition)*/
- + if (urdm->imr_reg & isr_reg & BIT_RXLEV) {
- + urdm->imr_reg &= ~BIT_RXLEV;
- + msm_uartdm_write(UART_DM_IMR, urdm->imr_reg);
- + queue_work(urdm->uartdm_wq, &urdm->rcv_1byte_work);
- + pr_debug(PRT_NAME ": RX lev -> Rcv 1byte callback.\n");
- + }
- + /* RX Stale (RXDM timeout)*/
- + else if (urdm->imr_reg & isr_reg & BIT_RXSTALE) {
- + urdm->imr_reg &= ~BIT_RXSTALE;
- + msm_uartdm_write(UART_DM_IMR, urdm->imr_reg);
- + msm_dmov_flush(urdm->pfdata->chan_uartdm_rx);
- + pr_debug(PRT_NAME ": RX stale -> Graceful flush.\n");
- + }
- + /* TX Ready (TX completion) */
- + else if (urdm->imr_reg & isr_reg & BIT_TX_READY) {
- + urdm->imr_reg &= ~BIT_TX_READY;
- + msm_uartdm_write(UART_DM_IMR, urdm->imr_reg);
- + msm_uartdm_write(UART_DM_CR, GCMD_RESET_TX_READY_INTERRUPT);
- + queue_work(urdm->uartdm_wq, &urdm->tx_end_work);
- + pr_debug(PRT_NAME ": TX ready.\n");
- + }
- + /* Unknown IRQ reason */
- + else {
- + spin_unlock_irqrestore(&urdm->lock, flags);
- + return IRQ_NONE;
- + }
- +
- + spin_unlock_irqrestore(&urdm->lock, flags);
- +
- + return IRQ_HANDLED;
- +}
- +
- +/**
- + * @brief Start MSM UARTDM RX transfer
- + * @details This function executes;\n
- + * # Check UARTDM port\n
- + * # Check UARTDM RX overrun\n
- + * # Direct RX DMA path\n
- + * # Enable RX Stale IRQ\n
- + * # UARTDM command (Enable stale event)\n
- + * # Enqueue RX DMA command\n
- + * # Write DMRX register
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -ENODEV = UARTDM not opened.\n
- + * -EIO = UARTDM RX overrun
- + */
- +int msm_uartdm_rx_start(void)
- +{
- + unsigned int sr;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check UARTDM port */
- + if (!urdm->vaddr_uartdm) {
- + pr_err(PRT_NAME ": Error. UARTDM not opened.\n");
- + return -ENODEV;
- + }
- +
- + /* Check UARTDM RX overrun */
- + sr = msm_uartdm_read(UART_DM_SR);
- + if (sr & BIT_UART_OVERRUN) {
- + pr_err(PRT_NAME ": Warning. UART RX overran.\n");
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_ERROR_STATUS);
- + return -EIO;
- + }
- +
- + /* Direct RX DMA path */
- + urdm->rxbox->dst_row_addr = felica_rxbuf_push_pointer();
- + if (urdm->rxbox->dst_row_addr) {
- + urdm->rxbox->row_offset = UARTDM_BURST_SIZE;
- + } else {
- + urdm->rxbox->dst_row_addr = urdm->dummy_dst_dmabase;
- + urdm->rxbox->row_offset = 0x0;
- + }
- +
- + /* Enable RX Stale IRQ */
- + urdm->imr_reg |= BIT_RXSTALE;
- + msm_uartdm_write(UART_DM_IMR, urdm->imr_reg);
- +
- + /* UARTDM command (Enable stale event) */
- + msm_uartdm_write(UART_DM_CR, GCMD_ENABLE_STALE_EVENT);
- +
- + /* Enqueue RX DMA command */
- + msm_dmov_enqueue_cmd(urdm->pfdata->chan_uartdm_rx, &urdm->rxdmov_cmd);
- +
- + /* Write DMRX register */
- + msm_uartdm_write(UART_DM_DMRX, LOCAL_UARTDM_RX_FIFO_SIZE);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Reset MSM UARTDM RX port
- + * @details This function executes;\n
- + * # Check UARTDM port\n
- + * # UARTDM command (Disable UARTDM RX)\n
- + * # UARTDM command (Reset UARTDM RX)\n
- + * # UARTDM command (Reset Error&Stale)\n
- + * # Clear RX buffer\n
- + * # Call RX DMA reset\n
- + * # UARTDM command (Enable UARTDM RX)
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -ENODEV = UARTDM not opened.
- + * @note
- + */
- +int msm_uartdm_rx_reset(void)
- +{
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check UARTDM port */
- + if (!urdm->vaddr_uartdm) {
- + pr_err(PRT_NAME ": Error. UARTDM not opened.\n");
- + return -ENODEV;
- + }
- +
- + msm_uartdm_write(UART_DM_CR, BIT_UART_RX_DISABLE);
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_RECEIVER);
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_ERROR_STATUS);
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_STALE_INTERRUPT);
- + felica_rxbuf_clear();
- + msm_uartdm_rxdmov_reset();
- + msm_uartdm_write(UART_DM_CR, BIT_UART_RX_EN);
- +
- + return 0;
- +}
- +
- +
- +/**
- + * @brief Start MSM UARTDM TX transfer
- + * @details This function executes;\n
- + * # Check UARTDM port\n
- + * # Count data in TX buffer\n
- + * # Get TX buffer pointer\n
- + * # Update TX buffer information
- + * # Enqueue TX DMA command\n
- + * # Write NO_CHARS_FOR_TX register\n
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Failure.\n
- + * -ENODEV = UARTDM not opened / Cannot access TX buf\n
- + * -EFAULT = Cannot update TX buf\n
- + * -ENODATA = No TX data exists.
- + * @note
- + */
- +int msm_uartdm_tx_start(void)
- +{
- + int cnt, ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check UARTDM port */
- + if (!urdm->vaddr_uartdm) {
- + pr_err(PRT_NAME ": Error. UARTDM not opened.\n");
- + return -ENODEV;
- + }
- +
- + /* Count data in TX buffer */
- + cnt = felica_txbuf_count();
- +
- + if (!cnt) {
- + pr_err(PRT_NAME ": Error. No TX data exists.\n");
- + return -ENODATA;
- + } else if (0 < cnt) {
- + /* Get TX buf pointer */
- + urdm->txbox->src_row_addr = felica_txbuf_pull_pointer();
- + urdm->txbox->num_rows = (((cnt + 15) >> 4) << 16)
- + | ((cnt + 15) >> 4);
- + /* Update TX buffer information */
- + ret = felica_txbuf_pull_status_update(cnt);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot update TX buf.\n");
- + return -EFAULT;
- + }
- + /* Enqueue TX DMA command */
- + msm_dmov_enqueue_cmd(urdm->pfdata->chan_uartdm_tx,
- + &urdm->txdmov_cmd);
- + /* Write NO_CHAR_FOR_TX register */
- + msm_uartdm_write(UART_DM_NO_CHARS_FOR_TX, cnt);
- + } else {
- + pr_err(PRT_NAME ": Error. Cannot access TX buf.\n");
- + return -ENODEV;
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Reset MSM UARTDM TX port
- + * @details This function executes;\n
- + * # Check UARTDM port\n
- + * # UARTDM command (Disable UARTDM TX)\n
- + * # UARTDM command (Reset UARTDM TX)\n
- + * # UARTDM command (Reset Error)\n
- + * # Clear TX buffer\n
- + * # UARTDM command (Enable UARTDM TX)
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -ENODEV = UARTDM not opened.
- + */
- +int msm_uartdm_tx_reset(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check UARTDM port */
- + if (!urdm->vaddr_uartdm) {
- + pr_err(PRT_NAME ": Error. UARTDM not opened.\n");
- + return -ENODEV;
- + }
- +
- + msm_uartdm_write(UART_DM_CR, BIT_UART_TX_DISABLE);
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_TRANSMITTER);
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_ERROR_STATUS);
- + felica_txbuf_clear();
- + msm_uartdm_write(UART_DM_CR, BIT_UART_TX_EN);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Enable interrupt of 1byte reception (RXLEV)
- + * @details This function executes;\n
- + * # Check UARTDM port\n
- + * # Enable UARTDM RXLEV IRQ
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -ENODEV = UARTDM not opened.
- + * @note
- + */
- +int msm_uartdm_rcv_1byte_enable(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check UARTDM port */
- + if (!urdm->vaddr_uartdm) {
- + pr_err(PRT_NAME ": Error. UARTDM not opened.\n");
- + return -ENODEV;
- + }
- +
- + urdm->imr_reg |= BIT_RXLEV;
- + msm_uartdm_write(UART_DM_IMR, urdm->imr_reg);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Disable interrupt of 1byte reception (RXLEV)
- + * @details This function executes;\n
- + * # Check UARTDM port\n
- + * # Disable UARTDM RXLEV IRQ
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -ENODEV = UARTDM not opened.
- + * @note
- + */
- +int msm_uartdm_rcv_1byte_disable(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check UARTDM port */
- + if (!urdm->vaddr_uartdm) {
- + pr_err(PRT_NAME ": Error. UARTDM not opened.\n");
- + return -ENODEV;
- + }
- +
- + urdm->imr_reg &= ~BIT_RXLEV;
- + msm_uartdm_write(UART_DM_IMR, urdm->imr_reg);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Check data length in UARTDM RX FIFO
- + * @details This function executes;\n
- + * # Check UARTDM port\n
- + * # Read UARTDM SR & DMRX register
- + * @param N/A
- + * @retval 0/Positive : Success. Length of data in RX FIFO.
- + * @retval Negative : Failure\n
- + * -ENODEV = UARTDM not opened.
- + * @note
- + */
- +int msm_uartdm_rcv_byte_check(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check UARTDM port */
- + if (!urdm->vaddr_uartdm) {
- + pr_err(PRT_NAME ": Error. UARTDM not opened.\n");
- + return -ENODEV;
- + }
- +
- + if (!(msm_uartdm_read(UART_DM_SR) & BIT_RXRDY))
- + return 0;
- +
- + return (int) msm_uartdm_read(UART_DM_DMRX) & BIT_RX_DM_CRCI_CHARS;
- +}
- +
- +/**
- + * @brief Work function of RX 1byte reception
- + * @details This function executes;\n
- + * # If registered, call the callback function.
- + * @param work : (unused)
- + * @retval N/A
- + * @note
- + */
- +static void msm_uartdm_rcv_1byte_work(struct work_struct *work)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (urdm->pfdata->callback_rcv_1byte)
- + urdm->pfdata->callback_rcv_1byte();
- +}
- +
- +/**
- + * @brief Work function of UARTDM RX End
- + * @details This function executes;\n
- + * # [If UART opened,] check RX_TOTAL_BYTE register.\n
- + * # [If UART opened,] update RX buffer with the data length.\n
- + * # [If registered,] call the callback function.
- + * @param work : (unused)
- + * @retval N/A
- + * @note
- + */
- +static void msm_uartdm_rx_end_work(struct work_struct *work)
- +{
- + unsigned int cnt;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (urdm->vaddr_uartdm) {
- + cnt = msm_uartdm_read(UART_DM_RX_TOTAL_SNAP)
- + & BIT_RX_TOTAL_BYTES;
- + pr_debug(PRT_NAME ": RX_TOTAL_SNAP = %d\n", cnt);
- + felica_rxbuf_push_status_update(cnt);
- + } else
- + pr_warning(PRT_NAME ": Warning. rx_end_work @ UART closed.\n");
- +
- + if (urdm->pfdata->callback_rx_complete)
- + urdm->pfdata->callback_rx_complete();
- +}
- +
- +/**
- + * @brief Work function of UARTDM RX Error
- + * @details This function executes;\n
- + * # If registered, call the callback function.
- + * @param work : (unused)
- + * @retval N/A
- + */
- +static void msm_uartdm_rx_error_work(struct work_struct *work)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (urdm->pfdata->callback_rx_error)
- + urdm->pfdata->callback_rx_error();
- +}
- +
- +/**
- + * @brief Work function of UARTDM TX End
- + * @details This function executes;\n
- + * # If registered, call the callback function.
- + * @param work : (unused)
- + * @retval N/A
- + * @note
- + */
- +static void msm_uartdm_tx_end_work(struct work_struct *work)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (urdm->pfdata->callback_tx_complete)
- + urdm->pfdata->callback_tx_complete();
- +}
- +
- +/**
- + * @brief Work function of UARTDM TX Error
- + * @details This function executes;\n
- + * # If registered, call the callback function.
- + * @param work : (unused)
- + * @retval N/A
- + * @note
- + */
- +static void msm_uartdm_tx_error_work(struct work_struct *work)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + if (urdm->pfdata->callback_tx_error)
- + urdm->pfdata->callback_tx_error();
- +}
- +
- +/**
- + * @brief Open MSM UARTDM port
- + * @details This function executes;\n
- + * # Check UARTDM sub-module data\n
- + * # UARTDM IRQ registration\n
- + * # UARTDM MIMO remap\n
- + * # Start UARTDM clock \n
- + * # UARTDM register setting\n
- + * # UARTDM command (Cmd reg protection)\n
- + * # UARTDM command (Reset RX & TX)\n
- + * # UARTDM command (Reset Error & Stale)\n
- + * # UARTDM command (Enable RX & TX)\n
- + * # Clear TX & RX buffer\n
- + * # Init DMA command boxes (TX)\n
- + * # Init DMA command boxes (RX)\n
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -ENODEV = UARTDM not initialized / Request IRQ error /
- + * Clock cannot be configured.\n
- + * -ENOMEM = UARTDM MMIO remap error
- + */
- +int msm_uartdm_open(void)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check UARTDM sub-module data */
- + if (!urdm) {
- + pr_err(PRT_NAME ": Error. UARTDM not initialized.\n");
- + return -ENODEV;
- + }
- +
- + /* UARTDM IRQ registration */
- + ret = request_irq(urdm->pfdata->irq_uartdm, msm_uartdm_irq_handler,
- + IRQF_TRIGGER_HIGH, urdm->pfdata->irq_name, urdm->pfdata->clk_dev);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Request IRQ failed.\n");
- + ret = -ENODEV;
- + goto err_request_irq_uart;
- + }
- + urdm->imr_reg = 0x0;
- +
- + /* UARTDM MMIO remap */
- + urdm->iores_uartdm = request_mem_region(
- + (resource_size_t) urdm->pfdata->paddr_uartdm, UARTDM_SIZE,
- + urdm->pfdata->iomem_name);
- + if (!urdm->iores_uartdm)
- + pr_warning(PRT_NAME ": Warning. UARTDM IOMEM conflict.\n");
- + urdm->vaddr_uartdm = ioremap_nocache(
- + (unsigned long) urdm->pfdata->paddr_uartdm, UARTDM_SIZE);
- + if (!urdm->vaddr_uartdm) {
- + pr_err(PRT_NAME ": Error. UARTDM IOremap failed.\n");
- + ret = -ENOMEM;
- + goto err_ioremap_uartdm;
- + }
- + pr_debug(PRT_NAME ": IOremap v-add 0x%x\n",
- + (int) urdm->vaddr_uartdm);
- +
- + /* Start UARTDM clock */
- + ret = clk_set_rate(urdm->clk_uartdm, LOCAL_UARTDM_BASE_FREQ);
- + ret |= clk_enable(urdm->clk_uartdm);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. UARTDM clock failed.\n");
- + ret = -ENODEV;
- + goto err_uartdm_clk_enable;
- + }
- +
- + /* UARTDM register setting */
- + /* + Baudrate setting */
- + msm_uartdm_write(UART_DM_CSR, LOCAL_UARTDM_BAUDRATE_CSR);
- + /* + Data-stop-parity setting (MR2) */
- + msm_uartdm_write(UART_DM_MR2, LOCAL_UARTDM_DATA_STOP_PARITY);
- + /* + UARTDM RX-TX buffer split setting */
- + msm_uartdm_write(UART_DM_BADR, LOCAL_UARTDM_TX_RX_FIFO_SPLIT);
- + /* + RX&TX wartermark setting */
- + msm_uartdm_write(UART_DM_TFWR, 0x0);
- + msm_uartdm_write(UART_DM_RFWR, 0x0);
- + /* + Stale time-out setting */
- + msm_uartdm_write(UART_DM_IPR,
- + (LOCAL_UARTDM_STALE_TIMEOUT & BIT_STALE_TIMEOUT_LSB) |
- + ((LOCAL_UARTDM_STALE_TIMEOUT << 2) & BIT_STALE_TIMEOUT_MSB));
- + /* + Enable TXDM and RXDM mode */
- + msm_uartdm_write(UART_DM_DMEN, BIT_RX_DM_EN | BIT_TX_DM_EN);
- + /* + Disable IrDA mode */
- + msm_uartdm_write(UART_DM_IRDA, 0x0);
- +
- + /* UARTDM command (Cmd reg protection) */
- + msm_uartdm_write(UART_DM_CR, GCMD_CR_PROTECTION_ENABLE);
- +
- + /* UARTDM command (Reset RX & TX) */
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_RECEIVER);
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_TRANSMITTER);
- +
- + /* UARTDM command (Reset Error & Stale) */
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_ERROR_STATUS);
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_STALE_INTERRUPT);
- +
- + /* UARTDM command (Enable RX & TX) */
- + msm_uartdm_write(UART_DM_CR, BIT_UART_TX_EN);
- + msm_uartdm_write(UART_DM_CR, BIT_UART_RX_EN);
- +
- + /* Clear TX & RX buffer */
- + felica_txbuf_clear();
- + felica_rxbuf_clear();
- +
- + /* Init DMA command boxes (TX) */
- + /* + TX DMOV mapping */
- + *urdm->txbox_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(urdm->mapped_txbox);
- + urdm->txdmov_cmd.cmdptr = DMOV_CMD_ADDR(urdm->mapped_txbox_ptr);
- + urdm->txdmov_cmd.complete_func = msm_uartdm_txdmov_callback;
- + urdm->txdmov_cmd.cmdptr = DMOV_CMD_ADDR(urdm->mapped_txbox_ptr);
- + urdm->txbox->cmd = CMD_LC | CMD_DST_CRCI(urdm->pfdata->crci_uartdm_tx)
- + | CMD_MODE_BOX;
- + /* + TX DMOV BOX command */
- + urdm->txbox->src_row_addr = 0x0;
- + urdm->txbox->dst_row_addr = (u32) urdm->pfdata->paddr_uartdm
- + + UART_DM_TF;
- + urdm->txbox->src_dst_len = (UARTDM_BURST_SIZE << 16)
- + | UARTDM_BURST_SIZE;
- + urdm->txbox->num_rows = 0x0;
- + urdm->txbox->row_offset = (UARTDM_BURST_SIZE << 16);
- +
- + /* Init DMA command boxes (RX) */
- + /* + RX DMOV mapping */
- + *urdm->rxbox_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(urdm->mapped_rxbox);
- + urdm->rxdmov_cmd.cmdptr = DMOV_CMD_ADDR(urdm->mapped_rxbox_ptr);
- + urdm->rxdmov_cmd.complete_func = msm_uartdm_rxdmov_callback;
- + urdm->rxdmov_cmd.cmdptr = DMOV_CMD_ADDR(urdm->mapped_rxbox_ptr);
- + urdm->rxbox->cmd = CMD_LC | CMD_SRC_CRCI(urdm->pfdata->crci_uartdm_rx)
- + | CMD_MODE_BOX;
- + /* + RX DMOV BOX command */
- + urdm->rxbox->src_row_addr = (u32) urdm->pfdata->paddr_uartdm
- + + UART_DM_RF;
- + urdm->rxbox->dst_row_addr = 0x0; /* Will be set later */
- + urdm->rxbox->src_dst_len = (UARTDM_BURST_SIZE << 16)
- + | UARTDM_BURST_SIZE;
- + urdm->rxbox->num_rows = ((LOCAL_UARTDM_RX_FIFO_SIZE >> 4) << 16)
- + | (LOCAL_UARTDM_RX_FIFO_SIZE >> 4);
- + urdm->rxbox->row_offset = 0x0; /* Will be set later */
- +
- + return 0;
- +
- +err_uartdm_clk_enable:
- + iounmap(urdm->vaddr_uartdm);
- + urdm->vaddr_uartdm = NULL;
- + if (urdm->iores_uartdm)
- + release_mem_region((u32) urdm->pfdata->paddr_uartdm,
- + UARTDM_SIZE);
- +err_ioremap_uartdm:
- + free_irq(urdm->pfdata->irq_uartdm, urdm->pfdata->clk_dev);
- +err_request_irq_uart:
- + return ret;
- +}
- +
- +/**
- + * @brief Close MSM UARTDM port
- + * @details This function executes;\n
- + * # Check UARTDM port\n
- + * # Reset RX DMA\n
- + * # Clear TX & RX buffer\n
- + * # UARTDM command (Disable RX & TX)\n
- + * # UARTDM command (Reset Error & Stale)\n
- + * # UARTDM command (Reset RX & TX)\n
- + * # Stop UARTDM clock\n
- + * # Release MIMO resource\n
- + * # Release UARTDM IRQ
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -ENODEV = UARTDM not opened.
- + * @note
- + */
- +int msm_uartdm_close(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Check UARTDM port */
- + if (!urdm->vaddr_uartdm) {
- + pr_err(PRT_NAME ": Error. UARTDM not opened.\n");
- + return -ENODEV;
- + }
- +
- + /* Reset RX DMA */
- + msm_uartdm_rxdmov_reset();
- +
- + /* Clear TX & RX buffer */
- + felica_txbuf_clear();
- + felica_rxbuf_clear();
- +
- + /* UARTDM command (Disable RX & TX) */
- + msm_uartdm_write(UART_DM_CR, BIT_UART_TX_DISABLE);
- + msm_uartdm_write(UART_DM_CR, BIT_UART_RX_DISABLE);
- +
- + /* UARTDM command (Reset Error & Stale) */
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_ERROR_STATUS);
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_STALE_INTERRUPT);
- +
- + /* UARTDM command (Reset RX & TX) */
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_RECEIVER);
- + msm_uartdm_write(UART_DM_CR, CCMD_RESET_TRANSMITTER);
- +
- + /* Stop UARTDM clock */
- + clk_disable(urdm->clk_uartdm);
- +
- + /* Release MIMO resource */
- + iounmap(urdm->vaddr_uartdm);
- + urdm->vaddr_uartdm = NULL;
- + if (urdm->iores_uartdm)
- + release_mem_region((u32) urdm->pfdata->paddr_uartdm,
- + UARTDM_SIZE);
- +
- + /* Release UARTDM IRQ */
- + free_irq(urdm->pfdata->irq_uartdm, urdm->pfdata->clk_dev);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Initialize MSM UARTDM port
- + * @details This function executes;\n
- + * # Alloc and Initialize UARTDM sub-module data\n
- + * # Get UARTDM clock device\n
- + * # Create workqueue of UARTDM\n
- + * # Set UARTDM call back functions\n
- + * # Call RX buffer init\n
- + * # Call TX buffer init\n
- + * # Alloc dummy DMA distination\n
- + * # Alloc DMA command boxes (RX & TX)
- + * @param N/A
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -EINVAL = No platform data\n
- + * -ENOMEM = No enough memory / Cannot create workqueue /
- + * RX/TX buffer initialization error
- + * -ENODEV = Clock device not found
- + * @note
- + */
- +int msm_uartdm_init(struct msm_uartdm_pfdata *pfdata)
- +{
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + /* Alloc and Initialize UARTDM sub-module data */
- + if (!pfdata) {
- + pr_err(PRT_NAME ": Error. No platform data for MSM UARTDM.\n");
- + return -EINVAL;
- + }
- + urdm = kzalloc(sizeof(struct msm_uartdm_data), GFP_KERNEL);
- + if (!urdm) {
- + pr_err(PRT_NAME ": Error. No enough mem for PON.\n");
- + ret = -ENOMEM;
- + goto err_alloc_uartdm_data;
- + }
- + urdm->pfdata = pfdata;
- +
- + /* Get UARTDM clock device */
- + urdm->clk_uartdm = clk_get(urdm->pfdata->clk_dev,
- + urdm->pfdata->clk_str);
- + if (IS_ERR(urdm->clk_uartdm)) {
- + pr_err(PRT_NAME ": Error. UARTDM clock failed.\n");
- + ret = -ENODEV;
- + goto err_get_uartdm_clock;
- + }
- +
- + spin_lock_init(&urdm->lock);
- +
- + /* Create workqueue of UARTDM */
- + urdm->uartdm_wq = create_workqueue(urdm->pfdata->workqueue_name);
- + if (!urdm->uartdm_wq) {
- + pr_err(PRT_NAME ": Error. Workqueue failed.\n");
- + ret = -ENOMEM;
- + goto err_create_workqueue;
- + }
- +
- + /* Set UARTDM call back functions */
- + INIT_WORK(&urdm->rcv_1byte_work, msm_uartdm_rcv_1byte_work);
- + INIT_WORK(&urdm->rx_end_work, msm_uartdm_rx_end_work);
- + INIT_WORK(&urdm->rx_error_work, msm_uartdm_rx_error_work);
- + INIT_WORK(&urdm->tx_end_work, msm_uartdm_tx_end_work);
- + INIT_WORK(&urdm->tx_error_work, msm_uartdm_tx_error_work);
- +
- + /* Call RX buffer init */
- + ret = felica_rxbuf_init();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. RX buffer init failed.\n");
- + ret = -ENOMEM;
- + goto err_rx_buf_init;
- + }
- +
- + /* Call TX buffer init */
- + ret = felica_txbuf_init();
- + if (ret) {
- + pr_err(PRT_NAME ": Error. TX buffer init failed.\n");
- + ret = -ENOMEM;
- + goto err_tx_buf_init;
- + }
- +
- + /* Alloc dummy DMA distination */
- + urdm->dummy_dst_buf = dma_alloc_coherent(NULL,
- + sizeof(char) * UARTDM_BURST_SIZE,
- + &urdm->dummy_dst_dmabase, GFP_KERNEL);
- + if (!urdm->dummy_dst_buf) {
- + pr_err(PRT_NAME ": Error. Alloc dummy distination.\n");
- + ret = -ENOMEM;
- + goto err_alloc_dummy_dst;
- + }
- +
- + /* Alloc TX DMOV box */
- + urdm->txbox = dma_alloc_coherent(NULL, sizeof(dmov_box),
- + &urdm->mapped_txbox, GFP_KERNEL);
- + if (!urdm->txbox) {
- + pr_err(PRT_NAME ": Error. No enough mem for TXDM.\n");
- + ret = -ENOMEM;
- + goto err_alloc_txbox;
- + }
- + urdm->txbox_ptr = dma_alloc_coherent(NULL, sizeof(u32 *),
- + &urdm->mapped_txbox_ptr, GFP_KERNEL);
- + if (!urdm->txbox_ptr) {
- + pr_err(PRT_NAME ": Error. No enough mem for TXDM.\n");
- + ret = -ENOMEM;
- + goto err_alloc_txbox_ptr;
- + }
- +
- + /* Alloc RX DMOV box */
- + urdm->rxbox = dma_alloc_coherent(NULL, sizeof(dmov_box),
- + &urdm->mapped_rxbox, GFP_KERNEL);
- + if (!urdm->rxbox) {
- + pr_err(PRT_NAME ": Error. No enough mem for RXDM.\n");
- + ret = -ENOMEM;
- + goto err_alloc_rxbox;
- + }
- + urdm->rxbox_ptr = dma_alloc_coherent(NULL, sizeof(u32 *),
- + &urdm->mapped_rxbox_ptr, GFP_KERNEL);
- + if (!urdm->rxbox_ptr) {
- + pr_err(PRT_NAME ": Error. No enough mem for RXDM.\n");
- + ret = -ENOMEM;
- + goto err_alloc_rxbox_ptr;
- + }
- +
- + return 0;
- +
- +err_alloc_rxbox_ptr:
- + dma_free_coherent(NULL, sizeof(dmov_box), urdm->rxbox,
- + urdm->mapped_rxbox);
- +err_alloc_rxbox:
- + dma_free_coherent(NULL, sizeof(u32 *), urdm->txbox_ptr,
- + urdm->mapped_txbox_ptr);
- +err_alloc_txbox_ptr:
- + dma_free_coherent(NULL, sizeof(dmov_box), urdm->txbox,
- + urdm->mapped_txbox);
- +err_alloc_txbox:
- + dma_free_coherent(NULL, sizeof(char) * UARTDM_BURST_SIZE,
- + urdm->dummy_dst_buf, urdm->dummy_dst_dmabase);
- +err_alloc_dummy_dst:
- + felica_txbuf_exit();
- +err_tx_buf_init:
- + felica_rxbuf_exit();
- +err_rx_buf_init:
- + destroy_workqueue(urdm->uartdm_wq);
- +err_create_workqueue:
- +err_get_uartdm_clock:
- + kfree(urdm);
- + urdm = NULL;
- +err_alloc_uartdm_data:
- + return ret;
- +}
- +
- +/**
- + * @brief Unload MSM UARTDM data and release RX&TX buffers
- + * @details This function executes;\n
- + * # Release DMA command boxes (RX & TX)\n
- + * # Release dummy DMA distination\n
- + * # Release TX buffer\n
- + * # Release RX buffer\n
- + * # Destroy workqueue of UARTDM\n
- + * # Release UARTDM sub-module data
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void msm_uartdm_exit(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + dma_free_coherent(NULL, sizeof(u32 *), urdm->rxbox_ptr,
- + urdm->mapped_rxbox_ptr);
- + dma_free_coherent(NULL, sizeof(dmov_box), urdm->rxbox,
- + urdm->mapped_rxbox);
- + dma_free_coherent(NULL, sizeof(u32 *), urdm->txbox_ptr,
- + urdm->mapped_txbox_ptr);
- + dma_free_coherent(NULL, sizeof(dmov_box), urdm->txbox,
- + urdm->mapped_txbox);
- + dma_free_coherent(NULL, sizeof(char) * UARTDM_BURST_SIZE,
- + urdm->dummy_dst_buf, urdm->dummy_dst_dmabase);
- + felica_txbuf_exit();
- + felica_rxbuf_exit();
- + destroy_workqueue(urdm->uartdm_wq);
- + kfree(urdm);
- + urdm = NULL;
- +}
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/msm_uartdm.h b/4.1.B.0.479//vendor/semc/hardware/felica/msm_uartdm.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/msm_uartdm.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/msm_uartdm.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,189 @@
- +/* vendor/semc/hardware/felica/msm_uartdm.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _MSM_UARTDM_H
- +#define _MSM_UARTDM_H
- +
- +struct msm_uartdm_pfdata;
- +
- +int msm_uartdm_init(struct msm_uartdm_pfdata *pfdata);
- +void msm_uartdm_exit(void);
- +int msm_uartdm_open(void);
- +int msm_uartdm_close(void);
- +int msm_uartdm_rx_start(void);
- +int msm_uartdm_rx_reset(void);
- +int msm_uartdm_tx_start(void);
- +int msm_uartdm_tx_reset(void);
- +int msm_uartdm_rcv_1byte_enable(void);
- +int msm_uartdm_rcv_1byte_disable(void);
- +int msm_uartdm_rcv_byte_check(void);
- +
- +/**************************************/
- +/* MSM7x30 UART DM - Constant - */
- +/**************************************/
- +#define UARTDM_SIZE 0x1000
- +#define UARTDM_BURST_SIZE 16
- +
- +/********************************************/
- +/* MSM7x30 UART DM - Local constant - */
- +/********************************************/
- +#define LOCAL_UARTDM_BASE_FREQ (460800 * 16)
- +#define LOCAL_UARTDM_BAUDRATE_CSR 0xFF /* 460kbps */
- +#define LOCAL_UARTDM_DATA_STOP_PARITY 0x34 /* 8N1 */
- +#define LOCAL_UARTDM_STALE_TIMEOUT 32 /* [char times] */
- +#define LOCAL_UARTDM_TX_RX_FIFO_SPLIT 0x003C /* Tx240Byte vs Rx272Byte */
- +#define LOCAL_UARTDM_TX_FIFO_SIZE (4 * LOCAL_UARTDM_TX_RX_FIFO_SPLIT)
- +#define LOCAL_UARTDM_RX_FIFO_SIZE (512 - LOCAL_UARTDM_TX_FIFO_SIZE)
- +
- +/*********************************************/
- +/* MSM7x30 UART DM - Register offset - */
- +/*********************************************/
- +#define UART_DM_MR1 0x0000
- +#define UART_DM_MR2 0x0004
- +#define UART_DM_CSR 0x0008
- +#define UART_DM_SR 0x0008
- +#define UART_DM_CR 0x0010
- +#define UART_DM_MISR 0x0010
- +#define UART_DM_IMR 0x0014
- +#define UART_DM_ISR 0x0014
- +#define UART_DM_IPR 0x0018
- +#define UART_DM_TFWR 0x001C
- +#define UART_DM_RFWR 0x0020
- +#define UART_DM_HCR 0x0024
- +#define UART_DM_DMRX 0x0034
- +#define UART_DM_IRDA 0x0038
- +#define UART_DM_RX_TOTAL_SNAP 0x0038
- +#define UART_DM_DMEN 0x003C
- +#define UART_DM_NO_CHARS_FOR_TX 0x0040
- +#define UART_DM_BADR 0x0044
- +#define UART_DM_TESTSL 0x0048
- +#define UART_DM_TXFS 0x004c
- +#define UART_DM_RXFS 0x0050
- +#define UART_DM_MISR_MODE 0x0060
- +#define UART_DM_MISR_RESET 0x0064
- +#define UART_DM_MISR_EXPORT 0x0068
- +#define UART_DM_MISR_VAL 0x006c
- +#define UART_DM_TF 0x0070
- +#define UART_DM_TF_2 0x0074
- +#define UART_DM_TF_3 0x0078
- +#define UART_DM_TF_4 0x007c
- +#define UART_DM_RF 0x0070
- +#define UART_DM_RF_2 0x0074
- +#define UART_DM_RF_3 0x0078
- +#define UART_DM_RF_4 0x007C
- +#define UART_DM_SIM_CFG 0x0080
- +#define UART_DM_TEST_WR_ADDR 0x0084
- +#define UART_DM_TEST_WR_DATA 0x0088
- +#define UART_DM_TEST_RD_ADDR 0x008C
- +#define UART_DM_TEST_RD_DATA 0x0090
- +
- +/*****************************************************/
- +/* MSM7x30 UART DM - Register bit definition - */
- +/*****************************************************/
- +#define BIT_32BIT_ALL 0xFFFFFFFF
- +/*** UART_DM_MR2 (R/W) ***/
- +#define BIT_RX_ERROR_CHAR_OFF 0x0200
- +#define BIT_RX_BREAK_ZERO_CHAR_OFF 0x0100
- +#define BIT_ERROR_MODE 0x0040
- +#define BIT_BITS_PER_CHAR 0x0030
- +#define BIT_STOP_BIT_LEN 0x000C
- +#define BIT_PARITY_MODE 0x0003
- +/*** UART_DM_CSR (W) ***/
- +#define BIT_UART_RX_CLK_SEL 0x00F0
- +#define BIT_UART_TX_CLK_SEL 0x000F
- +/*** UART_DM_SR (R) ***/
- +#define BIT_RX_BREAK_START_LAST 0x0100
- +#define BIT_HUNT_CHAR 0x0080
- +#define BIT_RX_BREAK 0x0040
- +#define BIT_PAR_FRAME_ERR 0x0020
- +#define BIT_UART_OVERRUN 0x0010
- +#define BIT_TXEMT 0x0008
- +#define BIT_TXRDY 0x0004
- +#define BIT_RXFULL 0x0002
- +#define BIT_RXRDY 0x0001
- +/*** UART_DM_CR (W) ***/
- +#define BIT_CHANNEL_COMMAND_MSB 0x0800
- +#define BIT_GENERAL_COMMAND 0x0700
- +#define BIT_CHANNEL_COMMAND_LSB 0x00F0
- +#define BIT_UART_TX_DISABLE 0x0008
- +#define BIT_UART_TX_EN 0x0004
- +#define BIT_UART_RX_DISABLE 0x0002
- +#define BIT_UART_RX_EN 0x0001
- +/*** UART_DM_MISR (R) ***/
- +#define BIT_UART_MISR
- +/*** UART_DM_IMR (W) & UART_DM_ISR (R) ***/
- +#define BIT_PAR_FRAME_ERR_IRQ 0x1000
- +#define BIT_RXBREAK_END 0x0800
- +#define BIT_RXBREAK_START 0x0400
- +#define BIT_TX_DONE 0x0200
- +#define BIT_TX_ERROR 0x0100
- +#define BIT_TX_READY 0x0080
- +#define BIT_CURRENT_CTS 0x0040
- +#define BIT_DELTA_CTS 0x0020
- +#define BIT_RXLEV 0x0010
- +#define BIT_RXSTALE 0x0008
- +#define BIT_RXBREAK_CHANGE 0x0004
- +#define BIT_RXHUNT 0x0002
- +#define BIT_TXLEV 0x0001
- +/*** UART_DM_IPR (R/W) ***/
- +#define BIT_STALE_TIMEOUT_MSB 0xFFFFFF80
- +#define BIT_SAMPLE_DATA 0x0040
- +#define BIT_STALE_TIMEOUT_LSB 0x001F
- +/*** UART_DM_TFWR (R/W) ***/
- +#define BIT_TFW 0xFFFFFFFF
- +/*** UART_DM_RFWR (R/W) ***/
- +#define BIT_RFW 0xFFFFFFFF
- +/*** UART_DM_DMRX (W/R) ***/
- +#define BIT_RX_DM_CRCI_CHARS 0x01FFFFFF
- +/*** UART_DM_RX_TOTAL_SNAP (R) ***/
- +#define BIT_RX_TOTAL_BYTES 0x00FFFFFF
- +/*** UART_DM_DMEN (R/W) ***/
- +#define BIT_RX_DM_EN 0x0002
- +#define BIT_TX_DM_EN 0x0001
- +/*** UART_DM_NO_CHARS_FOR_TX (R/W) ***/
- +#define BIT_TX_TOTAL_TRANS_LEN 0x00FFFFFF
- +/*** UART_DM_BADR (R/W) ***/
- +#define BIT_RX_BASE_ADDR 0xFFFFFFFC
- +
- +/*********************************************************/
- +/* MSM7x30 UART DM - Command register definition - */
- +/*********************************************************/
- +/*** Channel Command (Bit11)---(Bit7)(Bit6)(Bit5)(Bit4) ***/
- +#define CCMD_NULL_COMMAND 0x00
- +#define CCMD_RESET_RECEIVER 0x10
- +#define CCMD_RESET_TRANSMITTER 0x20
- +#define CCMD_RESET_ERROR_STATUS 0x30
- +#define CCMD_BREAK_CHANGE_INTERRUPT 0x40
- +#define CCMD_START_BREAK 0x50
- +#define CCMD_STOP_BREAK 0x60
- +#define CCMD_RESET_CTS_N 0x70
- +#define CCMD_RESET_STALE_INTERRUPT 0x80
- +#define CCMD_PACKET_MODE 0x90
- +#define CCMD_MODE_RESET 0xC0
- +#define CCMD_SET_RFR_N 0xD0
- +#define CCMD_RESET_RFR_N 0xE0
- +#define CCMD_RESET_TX_ERROR 0x800
- +#define CCMD_CLEAR_TX_DONE 0x810
- +#define CCMD_RESET_BREAK_START_INTERRUPT 0x820
- +#define CCMD_BREAK_END_INTERRUPT 0x830
- +#define CCMD_RESET_PER_FRAME_ERR_INTERRUPT 0x840
- +
- +/*** General Command (Bit10)(Bit9)(Bit8) ***/
- +#define GCMD_NULL_COMMAND 0x000
- +#define GCMD_CR_PROTECTION_ENABLE 0x100
- +#define GCMD_CR_PROTECTION_DISABLE 0x200
- +#define GCMD_RESET_TX_READY_INTERRUPT 0x300
- +#define GCMD_ENABLE_STALE_EVENT 0x500
- +#define GCMD_DISABLE_STALE_EVENT 0x600
- +#define GCMD_SW_FORCE_STALE 0x400
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/msm_uartmux.c b/4.1.B.0.479//vendor/semc/hardware/felica/msm_uartmux.c
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/msm_uartmux.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/msm_uartmux.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,128 @@
- +/* vendor/semc/hardware/felica/msm_uartmux.c
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/kernel.h>
- +#include <linux/stddef.h>
- +#include <linux/mfd/pmic8058.h>
- +#include <linux/pmic8058-nfc.h>
- +#include "msm_uartmux.h"
- +
- +#define PRT_NAME "msm uartmux"
- +
- +/**
- + * @brief Get pmic device information
- + * @param N/A
- + * @retval Valid address : Pointer to PMIC device
- + * @retval NULL : Cannot find PM8058 device
- + */
- +static struct pm8058_chip *msm_uartmux_pmic_info(void)
- +{
- + struct pm8058_nfc_device *nfcdev;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + nfcdev = pm8058_nfc_request();
- + if (!nfcdev)
- + return NULL;
- + if (!nfcdev->pm_chip)
- + return NULL;
- +
- + return nfcdev->pm_chip;
- +}
- +
- +/**
- + * @brief Get uartmux state
- + * @param N/A
- + * @retval 0/Positive : Success, value of UART MUX.
- + * @retval Negative : Failure\n
- + * -ENODEV = Cannot find PM8058 device\n
- + * -EIO = Cannot read value from PM8058
- + */
- +int msm_uartmux_get(void)
- +{
- + static struct pm8058_chip *pmdev;
- + int ret;
- + char misc = 0x00;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + pmdev = msm_uartmux_pmic_info();
- + if (!pmdev) {
- + pr_err(PRT_NAME ": Error. Dev not found.\n");
- + return -ENODEV;
- + }
- +
- + ret = pm8058_read(pmdev, SSBI_REG_ADDR_MISC, &misc, 1);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot read UART MUX.\n");
- + return -EIO;
- + }
- +
- + misc &= PM8058_UART_MUX_MASK; /* Needed to delete unused bits */
- + pr_debug(PRT_NAME ": UART MUX = %d.\n", (int) misc);
- +
- + return (int) misc;
- +}
- +
- +/**
- + * @brief Set uartmux state
- + * @param value : Value to write.
- + * @retval 0 : Success
- + * @retval Negative : Failure\n
- + * -ENODEV = Cannot find PM8058 device\n
- + * -EIO = Cannot write value to PM8058
- + */
- +int msm_uartmux_set(int value)
- +{
- + struct pm8058_chip *pmdev;
- + int ret;
- +
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + pmdev = msm_uartmux_pmic_info();
- + if (!pmdev) {
- + pr_err(PRT_NAME ": Error. Dev not found.\n");
- + return -ENODEV;
- + }
- +
- + ret = pm8058_misc_control(pmdev, PM8058_UART_MUX_MASK, value);
- + if (ret) {
- + pr_err(PRT_NAME ": Error. Cannot write UART MUX.");
- + return -EIO;
- + }
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Init funtion for MSM UARTMUX
- + * @param N/A
- + * @retval 0 : Success
- + * @note No initialization is needed for UART MUX.
- + */
- +int msm_uartmux_init(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +
- + return 0;
- +}
- +
- +/**
- + * @brief Exit function for MSM UARTMUX
- + * @param N/A
- + * @retval N/A
- + * @note
- + */
- +void msm_uartmux_exit(void)
- +{
- + pr_debug(PRT_NAME ": %s\n", __func__);
- +}
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/msm_uartmux.h b/4.1.B.0.479//vendor/semc/hardware/felica/msm_uartmux.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/msm_uartmux.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/msm_uartmux.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,31 @@
- +/* vendor/semc/hardware/felica/msm_uartmux.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _MSM_UARTMUX_H
- +#define _MSM_UARTMUX_H
- +
- +#define SSBI_REG_ADDR_MISC 0x1CC
- +
- +#include <linux/mutex.h>
- +
- +int msm_uartmux_get(void);
- +int msm_uartmux_set(int);
- +
- +int msm_uartmux_init(void);
- +void msm_uartmux_exit(void);
- +
- +struct pm8058_nfc_device {
- + struct mutex nfc_mutex;
- + struct pm8058_chip *pm_chip;
- +};
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/felica/semc_felica_ext.h b/4.1.B.0.479//vendor/semc/hardware/felica/semc_felica_ext.h
- --- a/4.1.B.0.431//vendor/semc/hardware/felica/semc_felica_ext.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/felica/semc_felica_ext.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,69 @@
- +/* vendor/semc/hardware/felica/semc_felica_ext.h
- + *
- + * Copyright (C) 2010 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Hiroaki Kuriyama <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _SEMC_FELICA_EXT_H
- +#define _SEMC_FELICA_EXT_H
- +
- +/* FeliCa Platform Data structures */
- +struct msm_uartdm_pfdata {
- + char *paddr_uartdm;
- + int irq_uartdm;
- + char irq_name[16];
- + int chan_uartdm_tx;
- + int crci_uartdm_tx;
- + int chan_uartdm_rx;
- + int crci_uartdm_rx;
- + char clk_str[16];
- + struct device *clk_dev;
- + char workqueue_name[16];
- + char iomem_name[16];
- + void (*callback_rcv_1byte)(void);
- + void (*callback_rx_complete)(void);
- + void (*callback_rx_error)(void);
- + void (*callback_tx_complete)(void);
- + void (*callback_tx_error)(void);
- +};
- +
- +struct felica_uart_pfdata {
- + struct msm_uartdm_pfdata uartdm_pfdata;
- + int uartmux_neutral;
- + int uartmux_felica;
- +};
- +
- +struct felica_cen_pfdata {
- +};
- +
- +struct felica_pon_pfdata {
- + int gpio_pon;
- + int (*tvdd_on)(void);
- + void (*tvdd_off)(void);
- +};
- +
- +struct felica_rfs_pfdata {
- + int gpio_rfs;
- +};
- +
- +struct felica_int_pfdata {
- + int gpio_int;
- + int irq_int;
- +};
- +
- +struct felica_platform_data {
- + struct felica_uart_pfdata uart_pfdata;
- + struct felica_cen_pfdata cen_pfdata;
- + struct felica_pon_pfdata pon_pfdata;
- + struct felica_rfs_pfdata rfs_pfdata;
- + struct felica_int_pfdata int_pfdata;
- + int (*gpio_init)(void);
- +};
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/irda/Android.mk b/4.1.B.0.479//vendor/semc/hardware/irda/Android.mk
- --- a/4.1.B.0.431//vendor/semc/hardware/irda/Android.mk 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/irda/Android.mk 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,49 @@
- +ifeq ($(SEMC_CFG_IRDA_DRIVER),true)
- +
- +LOCAL_PATH:= $(call my-dir)
- +SAVED_LOCAL_PATH_IR:= $(LOCAL_PATH)
- +
- +include $(CLEAR_VARS)
- +
- +# now the part that is actually built
- +
- +LOCAL_PATH_ABS_IR := $(shell cd $(SAVED_LOCAL_PATH_IR) && pwd)
- +
- +BUILD_ROOT_IR := $(TARGET_OUT_INTERMEDIATES)/SEMC_MSM_IRDA_OBJ
- +
- +BUILD_SUBDIRS_IR := $(shell cd $(SAVED_LOCAL_PATH_IR) && find . -type d)
- +BUILD_SRC_IR := $(shell cd $(SAVED_LOCAL_PATH_IR) && find . -name \*[ch])
- +BUILD_MK_IR := $(shell cd $(SAVED_LOCAL_PATH_IR) && find . -name Makefile)
- +
- +REL_SUBDIRS_IR := $(addprefix $(SAVED_LOCAL_PATH_IR)/, $(BUILD_SUBDIRS_IR))
- +REL_SRC_IR := $(addprefix $(SAVED_LOCAL_PATH_IR)/, $(BUILD_SRC_IR))
- +REL_MK_IR := $(addprefix $(SAVED_LOCAL_PATH_IR)/, $(BUILD_MK_IR))
- +
- +
- +$(BUILD_ROOT_IR)/semc_msm_irda.ko: $(PRODUCT_OUT)/kernel irprep
- + @(cd $(BUILD_ROOT_IR); $(MAKE) KERNEL_DIR=$(ANDROID_PRODUCT_OUT)/obj/KERNEL_OBJ -f Makefile)
- +
- +
- +irprep: irsubdirs irsrc irmk
- +
- +irsubdirs: $(REL_SUBDIRS_IR)
- + @(for i in $(BUILD_SUBDIRS_IR); do mkdir -p $(BUILD_ROOT_IR)/$$i; done)
- +
- +irsrc: $(REL_SRC_IR) irsubdirs
- + @(for i in $(BUILD_SRC_IR); do test -e $(BUILD_ROOT_IR)/$$i || ln -sf $(LOCAL_PATH_ABS_IR)/$$i $(BUILD_ROOT_IR)/$$i; done)
- +
- +irmk: $(REL_MK_IR) irsubdirs
- + @(for i in $(BUILD_MK_IR); do test -e $(BUILD_ROOT_IR)/$$i || ln -sf $(LOCAL_PATH_ABS_IR)/$$i $(BUILD_ROOT_IR)/$$i; done)
- +
- +# copy the modules
- +files := semc_msm_irda.ko
- +
- +copy_to := $(addprefix $(TARGET_OUT)/lib/modules/,$(files))
- +copy_from := $(addprefix $(BUILD_ROOT_IR)/,$(files))
- +
- +$(TARGET_OUT)/lib/modules/%.ko : $(BUILD_ROOT_IR)/%.ko | $(ACP)
- + $(transform-prebuilt-to-target)
- +
- +ALL_PREBUILT += $(copy_to)
- +
- +endif
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/irda/Makefile b/4.1.B.0.479//vendor/semc/hardware/irda/Makefile
- --- a/4.1.B.0.431//vendor/semc/hardware/irda/Makefile 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/irda/Makefile 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,20 @@
- +#
- +# Makefile for semc_msm_irda_module
- +#
- +# Copyright 2011 Sony Ericsson Mobile Communications Japan Inc.
- +# All rights, including trade secret rights, reserved.
- +#
- +
- +# environment variables
- +CROSS_COMPILE := arm-eabi-
- +ARCH := arm
- +PWD := $(shell pwd)
- +
- +obj-m = semc_msm_irda.o
- +semc_msm_irda_module-objs = semc_msm_irda.o
- +
- +all:
- + $(MAKE) CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) -C $(KERNEL_DIR) M=$(PWD) modules
- +
- +clean:
- + $(MAKE) CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(ARCH) -C $(KERNEL_DIR) M=$(PWD) clean
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/irda/semc_msm_irda.c b/4.1.B.0.479//vendor/semc/hardware/irda/semc_msm_irda.c
- --- a/4.1.B.0.431//vendor/semc/hardware/irda/semc_msm_irda.c 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/irda/semc_msm_irda.c 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,1241 @@
- +/* drivers/serial/semc_irda/semc_msm_irda.c
- + *
- + * Copyright (C) 2011 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Manabu Yoshida <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/init.h>
- +#include <linux/types.h>
- +#include <linux/gpio.h>
- +#include <linux/fs.h>
- +#include <linux/miscdevice.h>
- +#include <linux/mfd/pmic8058.h>
- +#include <linux/pmic8058-nfc.h>
- +#include <linux/delay.h>
- +#include <linux/uaccess.h>
- +#include <linux/semaphore.h>
- +#include <linux/clk.h>
- +#include <linux/wait.h>
- +#include <linux/dma-mapping.h>
- +#include <linux/poll.h>
- +
- +#include <linux/serial_core.h>
- +
- +#include "semc_msm_irda.h"
- +
- +#include <mach/dma.h>
- +
- +#define DRV_NAME "semc-msm-irda"
- +#define DRV_VERSION "1.0"
- +
- +/* UART DM Register size */
- +#define UARTDM_SIZE 0x1000
- +#define UARTDM_BURST_SIZE 16
- +
- +/* UART DM Registers */
- +#define UARTDM_MR2 0x0004
- +#define UARTDM_CSR 0x0008 /* write only */
- +#define UARTDM_SR 0x0008 /* read only */
- +#define UARTDM_CR 0x0010 /* write only */
- +#define UARTDM_IMR 0x0014 /* write only */
- +#define UARTDM_ISR 0x0014 /* read only */
- +#define UARTDM_IPR 0x0018
- +#define UARTDM_TFWR 0x001c
- +#define UARTDM_RFWR 0x0020
- +#define UARTDM_DMRX 0x0034
- +#define UARTDM_IRDA 0x0038
- +#define UARTDM_RX_TOTAL_SNAP 0x0038 /* read only */
- +#define UARTDM_DMEN 0x003c
- +#define UARTDM_NCF_TX 0x0040
- +#define UARTDM_BADR 0x0044
- +#define UARTDM_TF 0x0070 /* write only */
- +#define UARTDM_RF 0x0070 /* read only */
- +
- +/* Bit Definition */
- +/* UARTDM_SR (R) */
- +#define BIT_TXEMT 0x0008
- +/* UARTDM_CR (W) */
- +#define BIT_UART_TX_DISABLE 0x0008
- +#define BIT_UART_TX_EN 0x0004
- +#define BIT_UART_RX_DISABLE 0x0002
- +#define BIT_UART_RX_EN 0x0001
- +/* UARTDM_IMR (W) */
- +#define BIT_TX_READY 0x0080
- +#define BIT_RXLEV 0x0010
- +#define BIT_RXSTALE 0x0008
- +/* UARTDM_IPR (R/W) */
- +#define BIT_STALE_TIMEOUT_MSB 0xFFFFFF80
- +#define BIT_STALE_TIMEOUT_LSB 0x001F
- +/* UARTDM_IRDA (W) */
- +#define BIT_MEDIUM_RATE_EN 0x0010
- +#define BIT_INVERT_IRDA_RX 0x0002
- +#define BIT_IRDA_EN 0x0001
- +/* UARTDM_RX_TOTAL_SNAP (R) */
- +#define BIT_RX_TOTAL_BYTES 0x00FFFFFF
- +/* UARTDM_DMEN (R/W) */
- +#define BIT_RX_DM_EN 0x0002
- +#define BIT_TX_DM_EN 0x0001
- +
- +/* Command Definition */
- +/* Channel Commands (Bit11)---(Bit7)(Bit6)(Bit5)(Bit4) */
- +#define CCMD_NULL_COMMAND 0x00
- +#define CCMD_RESET_RECEIVER 0x10
- +#define CCMD_RESET_TRANSMITTER 0x20
- +#define CCMD_RESET_ERROR_STATUS 0x30
- +#define CCMD_BREAK_CHANGE_INTERRUPT 0x40
- +#define CCMD_START_BREAK 0x50
- +#define CCMD_STOP_BREAK 0x60
- +#define CCMD_RESET_CTS_N 0x70
- +#define CCMD_RESET_STALE_INTERRUPT 0x80
- +#define CCMD_PACKET_MODE 0x90
- +#define CCMD_MODE_RESET 0xC0
- +#define CCMD_SET_RFR_N 0xD0
- +#define CCMD_RESET_RFR_N 0xE0
- +#define CCMD_RESET_TX_ERROR 0x800
- +#define CCMD_CLEAR_TX_DONE 0x810
- +#define CCMD_RESET_BREAK_START_INTERRUPT 0x820
- +#define CCMD_BREAK_END_INTERRUPT 0x830
- +#define CCMD_RESET_PER_FRAME_ERR_INTERRUPT 0x840
- +
- +/* General Commands -(Bit10)(Bit9)(Bit8)---- */
- +#define GCMD_NULL_COMMAND 0x000
- +#define GCMD_CR_PROTECTION_ENABLE 0x100
- +#define GCMD_CR_PROTECTION_DISABLE 0x200
- +#define GCMD_RESET_TX_READY_INTERRUPT 0x300
- +#define GCMD_ENABLE_STALE_EVENT 0x500
- +#define GCMD_DISABLE_STALE_EVENT 0x600
- +#define GCMD_SW_FORCE_STALE 0x400
- +
- +/* PM MISC reg*/
- +#define SSBI_REG_ADDR_MISC 0x1CC
- +
- +/* IrDA UART2DM settings */
- +#define IRUART_UARTDM_CLK(bps) (((bps) > 460800) ? (bps * 16) : 7372800)
- +#define IRUART_DEF_BAUDRATE_CSR 0x55 /* 9600 bps */
- +#define IRUART_DEF_RXSTALE 32 /* character times */
- +#define IRUART_DATA_STOP_PARITY 0x34 /* 8N1 */
- +
- +#define IRUART_FSYNC_TIMEOUT (3*HZ)
- +
- +/* IrDA UART settings */
- +#define IRUART_IRDA_EN (BIT_INVERT_IRDA_RX | BIT_IRDA_EN)
- +#define IRUART_IRDA_DISABLE 0x0
- +
- +enum irda_state {
- + IRDA_UART_CLOSE,
- + IRDA_UART_OPEN,
- +};
- +enum irda_overflow {
- + IRDA_NORMAL,
- + IRDA_OVERFLOW,
- +};
- +enum irda_rx_state {
- + IRDA_RX_IDLE,
- + IRDA_RX_START,
- + IRDA_RX_CB,
- +};
- +
- +struct pm8058_nfc_device {
- + struct mutex nfc_mutex;
- + struct pm8058_chip *pm_chip;
- +};
- +
- +struct irda_driver_data {
- + struct irda_platform_data *pfdata;
- +
- + struct pm8058_nfc_device *nfcdev;
- +
- + enum irda_state state;
- + enum irda_overflow rx_overflow;
- + enum irda_rx_state rx_state;
- + int bps;
- +
- + int refcount;
- + struct semaphore sem;
- + spinlock_t lock;
- +
- + u32 imr_reg;
- + wait_queue_head_t wait_tx;
- + wait_queue_head_t wait_rx;
- + int condition_tx;
- + int condition_rx;
- +
- + struct tasklet_struct tasklet_rxfer_s;
- + struct tasklet_struct tasklet_rxfer_e;
- + struct tasklet_struct tasklet_txfer;
- +
- + u8 *vaddr_uartdm;
- + struct resource *iores_uartdm;
- + struct clk *clk_uartdm;
- +
- + struct irtxbuf_all txbuf;
- + struct irrxbuf_all rxbuf;
- +
- + struct msm_dmov_cmd txdmov_cmd;
- + dmov_box *txbox;
- + u32 *txbox_ptr;
- + dma_addr_t mapped_txbox;
- + dma_addr_t mapped_txbox_ptr;
- +
- + struct msm_dmov_cmd rxdmov_cmd;
- + dmov_box *rxbox;
- + u32 *rxbox_ptr;
- + dma_addr_t mapped_rxbox;
- + dma_addr_t mapped_rxbox_ptr;
- +};
- +
- +/* Local datas */
- +static struct irda_driver_data *irc;
- +
- +/* Local functions */
- +static u32 msm_uartdm_read(u32 offset);
- +static void msm_uartdm_write(u32 offset, u32 value);
- +static void irda_txbuf_clear(struct irtxbuf_all *);
- +static void irda_rxbuf_clear(struct irrxbuf_all *);
- +static void irda_txdmov_callback(
- +struct msm_dmov_cmd *, unsigned int, struct msm_dmov_errdata *);
- +static void irda_rxdmov_callback(
- +struct msm_dmov_cmd *, unsigned int, struct msm_dmov_errdata *);
- +static void irda_uart_txfer_exec(unsigned long);
- +static void irda_uart_rxfer_start(unsigned long);
- +static void irda_uart_rxfer_end(unsigned long);
- +static irqreturn_t irda_uart_irq_handler(int, void *);
- +static unsigned int irda_baudrate_set(unsigned int bps);
- +
- +
- +static unsigned int msm_uartdm_read(u32 offset)
- +{
- + if (offset >= UARTDM_SIZE) {
- + printk(KERN_ERR DRV_NAME ": msm_uartdm_read invalid offset\n");
- + return 0x0;
- + }
- + return ioread32(irc->vaddr_uartdm + offset);
- +}
- +
- +static void msm_uartdm_write(u32 offset, u32 value)
- +{
- + if (offset >= UARTDM_SIZE) {
- + printk(KERN_ERR DRV_NAME ": msm_uartdm_write invalid offset\n");
- + return;
- + }
- + iowrite32(value, irc->vaddr_uartdm + offset);
- +}
- +
- +static void irda_txbuf_clear(struct irtxbuf_all *p_txbuf)
- +{
- + p_txbuf->ptr = 0;
- + p_txbuf->num = 0;
- +}
- +
- +static void irda_rxbuf_clear(struct irrxbuf_all *p_rxbuf)
- +{
- + p_rxbuf->wp = 0;
- + p_rxbuf->rp = 0;
- +}
- +
- +static void irda_txdmov_callback(
- + struct msm_dmov_cmd *cmd_ptr,
- + unsigned int result,
- + struct msm_dmov_errdata *err)
- +{
- + unsigned long flags;
- +
- + WARN_ON(result != 0x80000002); /* DMA did not finish properly */
- +
- + spin_lock_irqsave(&irc->lock, flags);
- + irc->imr_reg |= BIT_TX_READY;
- + msm_uartdm_write(UARTDM_IMR, irc->imr_reg);
- + spin_unlock_irqrestore(&irc->lock, flags);
- +}
- +
- +static void irda_rxdmov_callback(
- + struct msm_dmov_cmd *cmd_ptr, unsigned int result,
- + struct msm_dmov_errdata *err)
- +{
- + if (irc->rx_state == IRDA_RX_START) {
- + irc->rx_state = IRDA_RX_CB;
- + tasklet_schedule(&irc->tasklet_rxfer_e);
- + } else {
- + printk(KERN_INFO DRV_NAME ": rxdmov callback is invalid.\n");
- + }
- +}
- +
- +static void irda_uart_rxfer_start(unsigned long data)
- +{
- + unsigned long flags;
- +
- + spin_lock_irqsave(&irc->lock, flags);
- +
- + if (irc->rx_state != IRDA_RX_IDLE) {
- + printk(KERN_INFO DRV_NAME ": rx state is not idle (%d).\n",
- + irc->rx_state);
- + goto out;
- + }
- + irc->rx_state = IRDA_RX_START;
- +
- + /* Update DMOV destination */
- + irc->rxbox->dst_row_addr = irc->rxbuf.dmabase;
- +
- + /* Enqueue RX DMOV request */
- + msm_dmov_enqueue_cmd(irc->pfdata->chan_uartdm_rx, &irc->rxdmov_cmd);
- +
- + /* Write DMRX register*/
- + msm_uartdm_write(UARTDM_DMRX, IRUART_SW_RXBUF_SIZE);
- +
- + /* Enable RX stale*/
- + irc->imr_reg |= BIT_RXSTALE;
- + msm_uartdm_write(UARTDM_IMR, irc->imr_reg);
- + msm_uartdm_write(UARTDM_CR, GCMD_ENABLE_STALE_EVENT);
- +
- +out:
- + spin_unlock_irqrestore(&irc->lock, flags);
- +}
- +
- +static void irda_uart_rxfer_end(unsigned long data)
- +{
- + int num, wp, rp, wlen1, wlen2, remd;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&irc->lock, flags);
- +
- + irc->rx_state = IRDA_RX_IDLE;
- +
- + /* Disable and Reset RXSTALE */
- + irc->imr_reg &= ~BIT_RXSTALE;
- + msm_uartdm_write(UARTDM_IMR, irc->imr_reg);
- + msm_uartdm_write(UARTDM_CR, GCMD_DISABLE_STALE_EVENT);
- + msm_uartdm_write(UARTDM_CR, CCMD_RESET_STALE_INTERRUPT);
- +
- + if (irc->rx_overflow == IRDA_OVERFLOW) {
- + printk(KERN_ERR DRV_NAME ": RX SW buf overflowed.\n");
- + num = 0;
- + goto out;
- + }
- +
- + /* Update SW RX ring buffer */
- + num = msm_uartdm_read(UARTDM_RX_TOTAL_SNAP) & BIT_RX_TOTAL_BYTES;
- + wlen1 = 0;
- + wlen2 = 0;
- + wp = irc->rxbuf.wp;
- + rp = irc->rxbuf.rp;
- +
- + /* Get remainder of ring buffer */
- + remd = 0;
- + if (wp < rp)
- + remd = irc->rxbuf.rp - irc->rxbuf.wp;
- + else
- + remd = (IRUART_SW_RXRINGBUF_SIZE - irc->rxbuf.wp)
- + + irc->rxbuf.rp;
- + if (remd <= num) {
- + irc->rx_overflow = IRDA_OVERFLOW;
- + printk(KERN_ERR DRV_NAME ": RX SW buf overflowed.\n");
- + printk(KERN_ERR DRV_NAME ": num(%d), remd(%d).\n", num, remd);
- + num = remd;
- + }
- +
- + if ((wp + num) > IRUART_SW_RXRINGBUF_SIZE) {
- + wlen1 = IRUART_SW_RXRINGBUF_SIZE - wp;
- + wlen2 = num - wlen1;
- + } else {
- + wlen1 = num;
- + wlen2 = 0;
- + }
- + if (wlen1) {
- + memcpy((irc->rxbuf.ringbuf + wp),
- + irc->rxbuf.buf, wlen1);
- + wp += wlen1;
- + }
- + if (wlen2) {
- + wp = 0;
- + memcpy((irc->rxbuf.ringbuf + wp),
- + (irc->rxbuf.buf + wlen1), wlen2);
- + wp += wlen2;
- + }
- + irc->rxbuf.wp = wp;
- +
- + if (irc->rxbuf.wp >= IRUART_SW_RXRINGBUF_SIZE)
- + irc->rxbuf.wp -= IRUART_SW_RXRINGBUF_SIZE;
- +
- + if (irc->rx_overflow != IRDA_OVERFLOW &&
- + (num == IRUART_SW_RXBUF_SIZE ||
- + (irc->bps == 115200 &&
- + (num == 128 || num == 256 || num == 384)))) {
- + printk(KERN_ERR DRV_NAME ": retry rxfer_start.\n");
- + spin_unlock_irqrestore(&irc->lock, flags);
- + irda_uart_rxfer_start(0);
- + spin_lock_irqsave(&irc->lock, flags);
- + } else {
- +out:
- + /* Enable RXLEV */
- + irc->imr_reg |= BIT_RXLEV;
- + msm_uartdm_write(UARTDM_IMR, irc->imr_reg);
- + }
- + irc->condition_rx = 1;
- + wake_up_interruptible(&irc->wait_rx);
- + spin_unlock_irqrestore(&irc->lock, flags);
- +}
- +
- +static void irda_uart_txfer_exec(unsigned long data)
- +{
- + int rest;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&irc->lock, flags);
- +
- + rest = irc->txbuf.num - irc->txbuf.ptr;
- + if (rest > 0) {
- + if (rest > IRUART_SW_TXBUF_SIZE)
- + rest = IRUART_SW_TXBUF_SIZE;
- + irc->txbox->src_row_addr = irc->txbuf.dmabase + irc->txbuf.ptr;
- + irc->txbox->num_rows =
- + ((rest + 15) >> 4 << 16) | (rest + 15) >> 4;
- + msm_dmov_enqueue_cmd(irc->pfdata->chan_uartdm_tx,
- + &irc->txdmov_cmd);
- + msm_uartdm_write(UARTDM_NCF_TX, rest);
- + irc->txbuf.ptr += rest;
- + }
- +
- + spin_unlock_irqrestore(&irc->lock, flags);
- +}
- +
- +static irqreturn_t irda_uart_irq_handler(int irq, void *dev)
- +{
- + u32 isr_reg;
- + unsigned long flags;
- +
- + spin_lock_irqsave(&irc->lock, flags);
- +
- + isr_reg = msm_uartdm_read(UARTDM_ISR);
- +
- + /* TX Ready (TX completion) */
- + if (isr_reg & BIT_TX_READY) {
- + irc->imr_reg &= ~BIT_TX_READY;
- + msm_uartdm_write(UARTDM_IMR, irc->imr_reg);
- + msm_uartdm_write(UARTDM_CR, GCMD_RESET_TX_READY_INTERRUPT);
- + if (irc->txbuf.num - irc->txbuf.ptr) {
- + tasklet_schedule(&irc->tasklet_txfer);
- + } else {
- + u32 sr_reg = msm_uartdm_read(UARTDM_SR);
- + while (!(sr_reg & BIT_TXEMT)) {
- + udelay(1); /* delay 1us */
- + sr_reg = msm_uartdm_read(UARTDM_SR);
- + }
- +
- + msm_uartdm_write(UARTDM_CR, BIT_UART_RX_EN);
- + irc->condition_tx = 1;
- + wake_up_interruptible(&irc->wait_tx);
- + }
- + }
- + /* RXLEV (1byte recognition)*/
- + if (isr_reg & BIT_RXLEV) {
- + irc->imr_reg &= ~BIT_RXLEV;
- + msm_uartdm_write(UARTDM_IMR, irc->imr_reg);
- + tasklet_schedule(&irc->tasklet_rxfer_s);
- + }
- + /* RX Stale (RXDM timeout)*/
- + if (isr_reg & BIT_RXSTALE) {
- + irc->imr_reg &= ~BIT_RXSTALE;
- + msm_uartdm_write(UARTDM_IMR, irc->imr_reg);
- + msm_dmov_flush(irc->pfdata->chan_uartdm_rx);
- + }
- +
- + spin_unlock_irqrestore(&irc->lock, flags);
- +
- + return IRQ_HANDLED;
- +}
- +
- +static unsigned int irda_baudrate_set(unsigned int bps)
- +{
- + unsigned long rxstale;
- + unsigned long iprdata;
- + u32 sr_reg;
- +
- + /* check the transmitter under-runs. */
- + sr_reg = msm_uartdm_read(UARTDM_SR);
- + if (!(sr_reg&BIT_TXEMT))
- + msleep(1);
- + if (!(sr_reg&BIT_TXEMT))
- + return -EBUSY;
- +
- + switch (bps) {
- + case B2400:
- + bps = 2400;
- + msm_uartdm_write(UARTDM_CSR, 0x33);
- + rxstale = 1;
- + break;
- + case B9600:
- + bps = 9600;
- + msm_uartdm_write(UARTDM_CSR, 0x55);
- + rxstale = 2;
- + break;
- + case B19200:
- + bps = 19200;
- + msm_uartdm_write(UARTDM_CSR, 0x77);
- + rxstale = 4;
- + break;
- + case B38400:
- + bps = 38400;
- + msm_uartdm_write(UARTDM_CSR, 0x99);
- + rxstale = 8;
- + break;
- + case B57600:
- + bps = 57600;
- + msm_uartdm_write(UARTDM_CSR, 0xaa);
- + rxstale = 16;
- + break;
- + case B115200:
- + bps = 115200;
- + msm_uartdm_write(UARTDM_CSR, 0xcc);
- + rxstale = 31;
- + break;
- + default:
- + /* default to 9600 */
- + printk(KERN_WARNING DRV_NAME
- + ": changed %d bps into 9600 bps of the default value.\n",
- + bps);
- + bps = 9600;
- + msm_uartdm_write(UARTDM_CSR, 0x55);
- + rxstale = 2;
- + break;
- + }
- +
- + irc->bps = bps;
- + if (clk_set_rate(irc->clk_uartdm, IRUART_UARTDM_CLK(bps))) {
- + printk(KERN_WARNING DRV_NAME
- + ": error setting clock rate on UART\n");
- + return -EIO;
- + }
- +
- + iprdata = rxstale & BIT_STALE_TIMEOUT_LSB;
- + iprdata |= BIT_STALE_TIMEOUT_MSB & (rxstale << 2);
- +
- + msm_uartdm_write(UARTDM_IPR, iprdata);
- +
- + return 0;
- +}
- +
- +static int irda_uart_open(struct inode *inode, struct file *file)
- +{
- + int ret;
- + u8 misc = 0x0;
- +
- + down(&irc->sem);
- + printk(KERN_INFO DRV_NAME ": %s\n", __func__);
- +
- + /* Check refcount */
- + if (irc->refcount > 0) {
- + irc->refcount++;
- + printk(KERN_INFO DRV_NAME
- + ": refirence counter count up(%d).\n", irc->refcount);
- + up(&irc->sem);
- + return 0;
- + }
- + /* PM8058-NFC Request */
- + irc->nfcdev = pm8058_nfc_request();
- + if (irc->nfcdev == NULL) {
- + printk(KERN_ERR DRV_NAME ": pm8058 nfc not found.\n");
- + ret = -ENODEV;
- + goto error_pm_nfc_request;
- + }
- +
- + /* PM8058 UART MUX setting */
- + ret = pm8058_read(irc->nfcdev->pm_chip, SSBI_REG_ADDR_MISC, &misc, 1);
- + if (ret)
- + printk(KERN_ERR DRV_NAME
- + ": cannot read pm8058 UART MUX reg.\n");
- + else
- + printk(KERN_INFO DRV_NAME ": misc register = %x\n", misc);
- + misc &= PM8058_UART_MUX_MASK;
- + switch (misc) {
- + case PM8058_UART_MUX_NO:
- + pm8058_misc_control(irc->nfcdev->pm_chip,
- + PM8058_UART_MUX_MASK, PM8058_UART_MUX_3);
- + printk(KERN_INFO DRV_NAME
- + ": OK. UART MUX = neutral --> IrDA.\n");
- + break;
- + case PM8058_UART_MUX_1:
- + printk(KERN_ERR DRV_NAME ": Now, uart_mux = 1 (FeliCa)\n");
- + ret = -EBUSY;
- + goto err_set_uart_mux;
- + case PM8058_UART_MUX_2:
- + printk(KERN_ERR DRV_NAME ": Now, uart_mux = 2 (unknown)\n");
- + ret = -EBUSY;
- + goto err_set_uart_mux;
- + default:
- + printk(KERN_ERR DRV_NAME ": UART MUX unavaible.\n");
- + ret = -EIO;
- + goto err_set_uart_mux;
- + }
- +
- + /* init IMR value */
- + irc->imr_reg = 0x0;
- +
- + /* init wait queue */
- + init_waitqueue_head(&irc->wait_tx);
- + init_waitqueue_head(&irc->wait_rx);
- +
- + /* init tasklet */
- + tasklet_init(&irc->tasklet_rxfer_s, irda_uart_rxfer_start, 0);
- + tasklet_init(&irc->tasklet_rxfer_e, irda_uart_rxfer_end, 0);
- + tasklet_init(&irc->tasklet_txfer, irda_uart_txfer_exec, 0);
- +
- + /* Register UARTDM IRQ */
- + ret = request_irq(irc->pfdata->irq_uartdm, irda_uart_irq_handler,
- + IRQF_TRIGGER_HIGH, "irda_uart", irc);
- + if (ret) {
- + printk(KERN_ERR DRV_NAME ": request IRQ failed. (UARTDM)\n");
- + goto err_request_irq_uart;
- + }
- +
- + /* UARTDM ioremap */
- + /* memory protection */
- + irc->iores_uartdm = request_mem_region((u32) irc->pfdata->paddr_uartdm,
- + UARTDM_SIZE, "irda_uart");
- + if (!irc->iores_uartdm) {
- + printk(KERN_ERR DRV_NAME
- + ": UARTDM request_mem_region failed.\n");
- + ret = -EBUSY;
- + goto err_request_mem_region;
- + }
- + irc->vaddr_uartdm = ioremap_nocache((u32) irc->pfdata->paddr_uartdm,
- + UARTDM_SIZE);
- + if (!irc->vaddr_uartdm) {
- + printk(KERN_ERR DRV_NAME ": UARTDM ioremap failed.\n");
- + ret = -ENOMEM;
- + goto err_ioremap_uartdm;
- + }
- +
- + /* UARTDM clock set and start */
- + /* default 9600 bps */
- + irc->bps = 9600;
- + clk_set_rate(irc->clk_uartdm, IRUART_UARTDM_CLK(9600));
- + clk_enable(irc->clk_uartdm);
- + msm_uartdm_write(UARTDM_CSR, IRUART_DEF_BAUDRATE_CSR);
- +
- + /* UARTDM register setting */
- + /* Data-stop-parity setting (MR2) */
- + msm_uartdm_write(UARTDM_MR2, IRUART_DATA_STOP_PARITY);
- +
- + /* RX&TX wartermark setting */
- + msm_uartdm_write(UARTDM_TFWR, 0x0);
- + msm_uartdm_write(UARTDM_RFWR, 0x0);
- +
- + /* Stale time-out setting */
- + msm_uartdm_write(UARTDM_IPR,
- + (IRUART_DEF_RXSTALE & BIT_STALE_TIMEOUT_LSB)
- + | ((IRUART_DEF_RXSTALE << 2) & BIT_STALE_TIMEOUT_MSB));
- +
- + /* Enable TXDM and RXDM mode */
- + msm_uartdm_write(UARTDM_DMEN, BIT_RX_DM_EN|BIT_TX_DM_EN);
- +
- + /* Enable the IRDA transceiver */
- + msm_uartdm_write(UARTDM_IRDA, IRUART_IRDA_EN);
- +
- + /* TX DMOV mapping */
- + irc->txbox = dma_alloc_coherent(NULL, sizeof(dmov_box),
- + &irc->mapped_txbox, GFP_KERNEL);
- + if (!irc->txbox) {
- + printk(KERN_ERR DRV_NAME ": no enough mem for TX DMOV(1).\n");
- + ret = -ENOMEM;
- + goto err_alloc_txbox;
- + }
- + irc->txbox_ptr = dma_alloc_coherent(NULL, sizeof(u32 *),
- + &irc->mapped_txbox_ptr, GFP_KERNEL);
- + if (!irc->txbox_ptr) {
- + printk(KERN_ERR DRV_NAME ": no enough mem for TX DMOV(2).\n");
- + ret = -ENOMEM;
- + goto err_alloc_txbox_ptr;
- + }
- + *irc->txbox_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(irc->mapped_txbox);
- + irc->txdmov_cmd.cmdptr = DMOV_CMD_ADDR(irc->mapped_txbox_ptr);
- + irc->txdmov_cmd.complete_func = irda_txdmov_callback;
- + irc->txdmov_cmd.cmdptr = DMOV_CMD_ADDR(irc->mapped_txbox_ptr);
- + irc->txbox->cmd =
- + CMD_LC
- + | CMD_DST_CRCI(irc->pfdata->crci_uartdm_tx) | CMD_MODE_BOX;
- + /* TX DMOV BOX command */
- + irc->txbox->src_row_addr = 0x0;
- + irc->txbox->dst_row_addr = (u32)irc->pfdata->paddr_uartdm + UARTDM_TF;
- + irc->txbox->src_dst_len = (UARTDM_BURST_SIZE<<16)|UARTDM_BURST_SIZE;
- + irc->txbox->num_rows = 0x0;
- + irc->txbox->row_offset = (UARTDM_BURST_SIZE<<16);
- +
- + /* RX DMOV mapping */
- + irc->rxbox = dma_alloc_coherent(NULL, sizeof(dmov_box),
- + &irc->mapped_rxbox, GFP_KERNEL);
- + if (!irc->rxbox) {
- + printk(KERN_ERR DRV_NAME ": no enough mem for RX DMOV(1).\n");
- + ret = -ENOMEM;
- + goto err_alloc_rxbox;
- + }
- + irc->rxbox_ptr = dma_alloc_coherent(NULL, sizeof(u32 *),
- + &irc->mapped_rxbox_ptr, GFP_KERNEL);
- + if (!irc->rxbox_ptr) {
- + printk(KERN_ERR DRV_NAME ": no enough mem for RX DMOV(2).\n");
- + ret = -ENOMEM;
- + goto err_alloc_rxbox_ptr;
- + }
- + *irc->rxbox_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(irc->mapped_rxbox);
- + irc->rxdmov_cmd.cmdptr = DMOV_CMD_ADDR(irc->mapped_rxbox_ptr);
- + irc->rxdmov_cmd.complete_func = irda_rxdmov_callback;
- + irc->rxdmov_cmd.cmdptr = DMOV_CMD_ADDR(irc->mapped_rxbox_ptr);
- + irc->rxbox->cmd =
- + CMD_LC
- + | CMD_SRC_CRCI(irc->pfdata->crci_uartdm_rx)
- + | CMD_MODE_BOX;
- + /* RX DMOV BOX command */
- + irc->rxbox->src_row_addr =
- + (u32)irc->pfdata->paddr_uartdm + UARTDM_RF;
- + irc->rxbox->dst_row_addr = 0x0;
- + irc->rxbox->src_dst_len = (UARTDM_BURST_SIZE<<16)|UARTDM_BURST_SIZE;
- + irc->rxbox->num_rows =
- + (IRUART_SW_RXBUF_SIZE >> 4 << 16) | IRUART_SW_RXBUF_SIZE >> 4;
- + irc->rxbox->row_offset = UARTDM_BURST_SIZE;
- +
- + /* Enable Command Register Protection */
- + msm_uartdm_write(UARTDM_CR, GCMD_CR_PROTECTION_ENABLE);
- +
- + /* Reset TX and RX */
- + msm_uartdm_write(UARTDM_CR, CCMD_RESET_RECEIVER);
- + msm_uartdm_write(UARTDM_CR, CCMD_RESET_TRANSMITTER);
- + msm_uartdm_write(UARTDM_CR, CCMD_RESET_ERROR_STATUS);
- + msm_uartdm_write(UARTDM_CR, CCMD_RESET_STALE_INTERRUPT);
- +
- + /* Setting PM power on (Low) */
- + ret = pm8058_gpio_config(irc->pfdata->gpio_pow,
- + irc->pfdata->gpio_pwcfg_low);
- + if (ret) {
- + printk(KERN_ERR DRV_NAME ": pmic gpio write failed\n");
- + goto err_gpio_config;
- + }
- + /* Wait 200usec */
- + udelay(200);
- +
- + /* Enable Transmitter and Receiver */
- + msm_uartdm_write(UARTDM_CR, BIT_UART_TX_EN);
- + msm_uartdm_write(UARTDM_CR, BIT_UART_RX_EN);
- +
- + /* Clear UART SW buffer */
- + irda_txbuf_clear(&irc->txbuf);
- + irda_rxbuf_clear(&irc->rxbuf);
- +
- + /* init Overflow flag */
- + irc->rx_overflow = IRDA_NORMAL;
- +
- + /* Increment refcount */
- + irc->refcount++;
- +
- + /* (state change)--> IRDA_UART_OPEN */
- + irc->state = IRDA_UART_OPEN;
- + irc->rx_state = IRDA_RX_IDLE;
- +
- + printk(KERN_INFO DRV_NAME
- + ": succecssfly opened, refcount = %d\n", irc->refcount);
- +
- + /* Activate RXLEV IRQ */
- + irc->imr_reg |= BIT_RXLEV;
- + msm_uartdm_write(UARTDM_IMR, irc->imr_reg);
- +
- + up(&irc->sem);
- + return 0;
- +
- +/* Error handling */
- +err_gpio_config:
- + dma_free_coherent(NULL,
- + sizeof(u32 *), irc->rxbox_ptr, irc->mapped_txbox_ptr);
- +err_alloc_rxbox_ptr:
- + dma_free_coherent(NULL,
- + sizeof(dmov_box), irc->rxbox, irc->mapped_rxbox);
- +err_alloc_rxbox:
- + dma_free_coherent(NULL,
- + sizeof(u32 *), irc->txbox_ptr, irc->mapped_txbox_ptr);
- +err_alloc_txbox_ptr:
- + dma_free_coherent(NULL,
- + sizeof(dmov_box), irc->txbox, irc->mapped_txbox);
- +err_alloc_txbox:
- + msm_uartdm_write(UARTDM_IRDA, IRUART_IRDA_DISABLE);
- + clk_disable(irc->clk_uartdm);
- + iounmap(irc->vaddr_uartdm);
- +err_ioremap_uartdm:
- + release_mem_region((u32) irc->pfdata->paddr_uartdm, UARTDM_SIZE);
- +err_request_mem_region:
- + free_irq(irc->pfdata->irq_uartdm, irc);
- +err_request_irq_uart:
- + tasklet_kill(&irc->tasklet_rxfer_s);
- + tasklet_kill(&irc->tasklet_rxfer_e);
- + tasklet_kill(&irc->tasklet_txfer);
- + pm8058_misc_control(irc->nfcdev->pm_chip,
- + PM8058_UART_MUX_MASK, PM8058_UART_MUX_NO);
- +err_set_uart_mux:
- +error_pm_nfc_request:
- + up(&irc->sem);
- + return ret;
- +}
- +
- +static int irda_uart_release(struct inode *inode, struct file *file)
- +{
- + down(&irc->sem);
- + printk(KERN_INFO DRV_NAME ": %s\n", __func__);
- +
- + /* Decrement refcount */
- + irc->refcount--;
- +
- + /* Check refcount */
- + if (irc->refcount == 0) {
- + /* do discard flush */
- + if (irc->rx_state == IRDA_RX_START) {
- + irc->rx_state = IRDA_RX_IDLE;
- + msm_dmov_stop_cmd(irc->pfdata->chan_uartdm_rx,
- + &irc->rxdmov_cmd, 0);
- + }
- +
- + /* Deactivate RXLEV IRQ */
- + irc->imr_reg &= ~BIT_RXLEV;
- + msm_uartdm_write(UARTDM_IMR, irc->imr_reg);
- + /* (state change)--> IRDA_UART_OPEN */
- + irc->state = IRDA_UART_CLOSE;
- + /* Disable the IRDA transceiver */
- + msm_uartdm_write(UARTDM_IRDA, IRUART_IRDA_DISABLE);
- + /* Disable Transmitter and Receiver */
- + msm_uartdm_write(UARTDM_CR, BIT_UART_TX_DISABLE);
- + msm_uartdm_write(UARTDM_CR, BIT_UART_RX_DISABLE);
- +
- + /* Desable TXDM and RXDM mode */
- + msm_uartdm_write(UARTDM_DMEN, IRUART_IRDA_DISABLE);
- +
- + /* Wait 1usec */
- + udelay(1);
- + /* Setting PM power off (Hig) */
- + pm8058_gpio_config(irc->pfdata->gpio_pow,
- + irc->pfdata->gpio_pwcfg_hig);
- +
- + /* Clear UART SW buffer */
- + irda_txbuf_clear(&irc->txbuf);
- + irda_rxbuf_clear(&irc->rxbuf);
- + /* Reset TX and RX*/
- + msm_uartdm_write(UARTDM_CR, CCMD_RESET_RECEIVER);
- + msm_uartdm_write(UARTDM_CR, CCMD_RESET_TRANSMITTER);
- + msm_uartdm_write(UARTDM_CR, CCMD_RESET_ERROR_STATUS);
- + msm_uartdm_write(UARTDM_CR, CCMD_RESET_STALE_INTERRUPT);
- + /* Release DMOV data */
- + dma_free_coherent(NULL, sizeof(dmov_box),
- + irc->txbox, irc->mapped_txbox);
- + dma_free_coherent(NULL, sizeof(dmov_box),
- + irc->rxbox, irc->mapped_rxbox);
- + dma_free_coherent(NULL, sizeof(u32 *),
- + irc->txbox_ptr, irc->mapped_txbox_ptr);
- + dma_free_coherent(NULL, sizeof(u32 *),
- + irc->rxbox_ptr, irc->mapped_rxbox_ptr);
- + /* UARTDM clock stop */
- + clk_disable(irc->clk_uartdm);
- + /* UARTDM iounmap */
- + if (irc->iores_uartdm)
- + release_mem_region((u32) irc->pfdata->paddr_uartdm,
- + UARTDM_SIZE);
- + iounmap(irc->vaddr_uartdm);
- + /* Remove IRQ for UARTDM */
- + free_irq(irc->pfdata->irq_uartdm, irc);
- + /* Remove tasklets for UARTDM */
- + tasklet_kill(&irc->tasklet_rxfer_s);
- + tasklet_kill(&irc->tasklet_rxfer_e);
- + tasklet_kill(&irc->tasklet_txfer);
- + /* PM8058 UART MUX reset */
- + pm8058_misc_control(irc->nfcdev->pm_chip,
- + PM8058_UART_MUX_MASK, PM8058_UART_MUX_NO);
- + {
- + u8 misc = 0x0;
- + int ret = pm8058_read(irc->nfcdev->pm_chip,
- + SSBI_REG_ADDR_MISC, &misc, 1);
- + if (ret)
- + printk(KERN_ERR DRV_NAME
- + ": cannot read pm8058 UART MUX reg.\n");
- + else
- + printk(KERN_INFO DRV_NAME
- + ": misc register = %x\n", misc);
- + }
- + }
- + printk(KERN_INFO DRV_NAME ": Closed. Refcount = %d\n", irc->refcount);
- + up(&irc->sem);
- +
- + return 0;
- +}
- +
- +static ssize_t irda_uart_read(
- + struct file *file, char __user *buf,
- + size_t count, loff_t *offset)
- +{
- + int cnt, rest, srest1, srest2;
- + unsigned long flags;
- + int ret;
- +
- + down(&irc->sem);
- +
- + if (irc->state != IRDA_UART_OPEN) {
- + ret = -EHOSTUNREACH;
- + goto err_out;
- + }
- +
- + spin_lock_irqsave(&irc->lock, flags);
- + ret = (irc->rx_overflow == IRDA_NORMAL)
- + && (irc->rxbuf.wp == irc->rxbuf.rp);
- + if (ret)
- + irc->condition_rx = 0;
- + spin_unlock_irqrestore(&irc->lock, flags);
- +
- + cnt = 0;
- + if (ret) {
- + ret = wait_event_interruptible(irc->wait_rx, irc->condition_rx);
- + irc->condition_rx = 0;
- +
- + spin_lock_irqsave(&irc->lock, flags);
- + ret = (irc->rx_overflow == IRDA_NORMAL)
- + && (irc->rxbuf.wp == irc->rxbuf.rp);
- + spin_unlock_irqrestore(&irc->lock, flags);
- +
- + if (ret)
- + goto out;
- + }
- +
- + spin_lock_irqsave(&irc->lock, flags);
- + if (irc->rxbuf.wp > irc->rxbuf.rp) {
- + srest1 = irc->rxbuf.wp - irc->rxbuf.rp;
- + srest2 = 0;
- + } else {
- + srest1 = IRUART_SW_RXRINGBUF_SIZE - irc->rxbuf.rp;
- + srest2 = irc->rxbuf.wp;
- + }
- + rest = count - cnt;
- + spin_unlock_irqrestore(&irc->lock, flags);
- +
- + if (rest > srest1)
- + rest = srest1;
- + ret = copy_to_user(buf + cnt,
- + (irc->rxbuf.ringbuf + irc->rxbuf.rp), rest);
- + if (ret) {
- + ret = -EFAULT;
- + goto err_out;
- + }
- +
- + spin_lock_irqsave(&irc->lock, flags);
- + /* Update RX buf status */
- + irc->rxbuf.rp += rest;
- + if (irc->rxbuf.rp >= IRUART_SW_RXRINGBUF_SIZE)
- + irc->rxbuf.rp -= IRUART_SW_RXRINGBUF_SIZE;
- + cnt += rest;
- + spin_unlock_irqrestore(&irc->lock, flags);
- +
- + rest = count - cnt;
- + if (!rest || !srest2)
- + goto out;
- + if (rest > srest2)
- + rest = srest2;
- + ret = copy_to_user(buf + cnt,
- + (irc->rxbuf.ringbuf + irc->rxbuf.rp), rest);
- + if (ret) {
- + ret = -EFAULT;
- + goto err_out;
- + }
- +
- + spin_lock_irqsave(&irc->lock, flags);
- + /* Update RX buf status */
- + irc->rxbuf.rp += rest;
- + cnt += rest;
- + spin_unlock_irqrestore(&irc->lock, flags);
- +
- +out:
- + irc->rx_overflow = IRDA_NORMAL;
- +
- + up(&irc->sem);
- + return cnt;
- +
- +err_out:
- + printk(KERN_ERR DRV_NAME ": %s error(%d)\n", __func__, ret);
- + up(&irc->sem);
- + return ret;
- +}
- +
- +static ssize_t irda_uart_write(
- + struct file *file, const char __user *buf, size_t count, loff_t *offset)
- +{
- + int ret;
- +
- + down(&irc->sem);
- +
- + if (irc->state != IRDA_UART_OPEN) {
- + printk(KERN_ERR DRV_NAME
- + ": inconsistent state(%d).\n", irc->state);
- + ret = -EHOSTUNREACH;
- + goto err_out;
- + }
- +
- + if (count > IRUART_SW_TXBUF_SIZE) {
- + printk(KERN_ERR DRV_NAME
- + ": too many characters for write(%d).\n", count);
- + ret = -EINVAL;
- + goto err_out;
- + }
- +
- + irda_txbuf_clear(&irc->txbuf);
- +
- + if (copy_from_user(irc->txbuf.buf, buf, count)) {
- + ret = -EFAULT;
- + goto err_out;
- + }
- +
- + irc->txbuf.num = count;
- +
- + irc->condition_tx = 0;
- + msm_uartdm_write(UARTDM_CR, BIT_UART_RX_DISABLE);
- +
- + irda_uart_txfer_exec(0);
- +
- + if (!irc->condition_tx)
- + ret = wait_event_interruptible(irc->wait_tx, irc->condition_tx);
- + irc->condition_tx = 0;
- +
- + up(&irc->sem);
- + return irc->txbuf.num;
- +
- +err_out:
- + up(&irc->sem);
- + return ret;
- +}
- +
- +static unsigned int irda_uart_poll(
- + struct file *file, struct poll_table_struct *wait)
- +{
- + unsigned long flags;
- + int ret;
- + unsigned int mask = 0;
- +
- + down(&irc->sem);
- +
- + if (irc->state != IRDA_UART_OPEN) {
- + mask = POLLERR;
- + goto out;
- + }
- +
- + poll_wait(file, &irc->wait_rx, wait);
- + spin_lock_irqsave(&irc->lock, flags);
- + ret = (irc->rx_overflow == IRDA_NORMAL)
- + && (irc->rxbuf.wp == irc->rxbuf.rp);
- + if (!ret)
- + mask = POLLIN | POLLRDNORM;
- + mask |= POLLOUT | POLLWRNORM;
- + spin_unlock_irqrestore(&irc->lock, flags);
- +out:
- + up(&irc->sem);
- + return mask;
- +}
- +
- +#define IRUART_IOCTRL_BAUDRATE 0x0e000002
- +#define IRUART_IOCTRL_QRYINFRM 0x0e000005
- +static int irda_uart_ioctl(
- + struct inode *inode, struct file *file,
- + unsigned int cmd, unsigned long arg)
- +{
- + int ret;
- +
- + down(&irc->sem);
- +
- + switch (cmd) {
- + case IRUART_IOCTRL_BAUDRATE:
- + ret = irda_baudrate_set((unsigned int)arg);
- + if (ret) {
- + printk(KERN_ERR DRV_NAME ": baudrate set failed.\n");
- + goto err_out;
- + }
- + break;
- + default:
- + printk(KERN_ERR DRV_NAME ": Error. Unsupported IOCTL.\n");
- + ret = -ENOTTY;
- + goto err_out;
- + }
- +
- + up(&irc->sem);
- + return 0;
- +
- +err_out:
- + up(&irc->sem);
- + return ret;
- +}
- +
- +static const struct file_operations irc_fops = {
- + .owner = THIS_MODULE,
- + .read = irda_uart_read,
- + .write = irda_uart_write,
- + .poll = irda_uart_poll,
- + .ioctl = irda_uart_ioctl,
- + .open = irda_uart_open,
- + .release = irda_uart_release,
- +};
- +
- +static struct miscdevice irda_uart_device = {
- + .minor = MISC_DYNAMIC_MINOR,
- + .name = "irda_uart",
- + .fops = &irc_fops,
- +};
- +
- +static int __init irda_probe(struct platform_device *pdev)
- +{
- + int ret;
- +
- + irc = kzalloc(sizeof(struct irda_driver_data), GFP_KERNEL);
- + if (!irc) {
- + printk(KERN_ERR DRV_NAME ": could not allocate memory.\n");
- + ret = -ENOMEM;
- + goto error_alloc_driver_data;
- + }
- +
- + irc->pfdata = pdev->dev.platform_data;
- +
- + /* GPIO Setting */
- + ret = irc->pfdata->gpio_init();
- + if (ret && ret != -EBUSY) {
- + printk(KERN_ERR DRV_NAME ": gpio initialize failed.\n");
- + ret = -EIO;
- + goto error_gpio_init;
- + }
- +
- + /* Platform Clock */
- + irc->clk_uartdm = clk_get(irc->pfdata->clk_dev, irc->pfdata->clk_str);
- + if (IS_ERR(irc->clk_uartdm)) {
- + printk(KERN_ERR DRV_NAME ": clock assignment failed.\n");
- + ret = -ENODEV;
- + goto error_get_platform_clock;
- + }
- + /* init Ref count */
- + irc->refcount = 0;
- +
- + /* Alloc RX ring buffer */
- + irc->rxbuf.ringbuf = kzalloc(sizeof(u8)*(
- + IRUART_SW_RXRINGBUF_SIZE
- + + IRUART_SW_RXBUF_SIZE),
- + GFP_KERNEL);
- + if (!irc->rxbuf.ringbuf) {
- + printk(KERN_ERR DRV_NAME
- + ": could not allocate memory for RX ring buffer.\n");
- + ret = -ENOMEM;
- + goto error_alloc_rx_ringbuf;
- + }
- +
- + /* Alloc TX SW Buffer */
- + irc->txbuf.buf = dma_alloc_coherent(NULL,
- + sizeof(u8)*IRUART_SW_TXBUF_SIZE,
- + &irc->txbuf.dmabase, GFP_KERNEL);
- + if (!irc->txbuf.buf) {
- + printk(KERN_ERR DRV_NAME ": no enough mem for TXbuf.\n");
- + ret = -ENOMEM;
- + goto err_alloc_tx_buffer;
- + }
- +
- + /* Alloc RX SW Buffer */
- + irc->rxbuf.buf = dma_alloc_coherent(NULL,
- + sizeof(u8)*IRUART_SW_RXBUF_SIZE,
- + &irc->rxbuf.dmabase, GFP_KERNEL);
- + if (!irc->rxbuf.buf) {
- + printk(KERN_ERR DRV_NAME ": no enough mem for RXbuf.\n");
- + ret = -ENOMEM;
- + goto err_alloc_rx_buffer;
- + }
- +
- + irc->rx_overflow = IRDA_NORMAL;
- +
- + if (misc_register(&irda_uart_device)) {
- + printk(KERN_ERR DRV_NAME ": cannot register /dev/irda.\n");
- + ret = -EACCES;
- + goto err_register_uart_device;
- + }
- +
- + sema_init(&irc->sem, 1);
- + spin_lock_init(&irc->lock);
- +
- + irc->state = IRDA_UART_CLOSE;
- +
- + return 0;
- +
- +/* error handling */
- +err_register_uart_device:
- + dma_free_coherent(NULL, sizeof(u8)*IRUART_SW_RXBUF_SIZE,
- + irc->rxbuf.buf, irc->rxbuf.dmabase);
- +err_alloc_rx_buffer:
- + dma_free_coherent(NULL, sizeof(u8)*IRUART_SW_TXBUF_SIZE,
- + irc->txbuf.buf, irc->txbuf.dmabase);
- +err_alloc_tx_buffer:
- + kfree(irc->rxbuf.ringbuf);
- +error_alloc_rx_ringbuf:
- +error_get_platform_clock:
- +error_gpio_init:
- + kfree(irc);
- +error_alloc_driver_data:
- + return ret;
- +}
- +
- +static int __devexit irda_remove(struct platform_device *pdev)
- +{
- + printk(KERN_INFO DRV_NAME ": %s\n", __func__);
- +
- + misc_deregister(&irda_uart_device);
- +
- + dma_free_coherent(NULL, sizeof(u8)*IRUART_SW_TXBUF_SIZE,
- + irc->txbuf.buf, irc->txbuf.dmabase);
- + dma_free_coherent(NULL, sizeof(u8)*IRUART_SW_RXBUF_SIZE,
- + irc->rxbuf.buf, irc->rxbuf.dmabase);
- + kfree(irc);
- + return 0;
- +}
- +
- +static int irda_suspend(struct platform_device *pdev,
- + pm_message_t message)
- +{
- + printk(KERN_INFO DRV_NAME ": %s\n", __func__);
- + return 0;
- +}
- +
- +static int irda_resume(struct platform_device *pdev)
- +{
- + printk(KERN_INFO DRV_NAME ": %s\n", __func__);
- + return 0;
- +}
- +
- +static struct platform_driver semc_msm_irda = {
- + .probe = irda_probe,
- + .remove = irda_remove,
- + .suspend = irda_suspend,
- + .resume = irda_resume,
- + .driver = {
- + .name = "semc-msm-irda",
- + .owner = THIS_MODULE,
- + },
- +};
- +
- +static int __init irda_init(void)
- +{
- + int ret;
- + printk(KERN_INFO DRV_NAME ": %s\n", __func__);
- + ret = platform_driver_register(&semc_msm_irda);
- +
- + return ret;
- +}
- +
- +static void __exit irda_exit(void)
- +{
- + printk(KERN_INFO DRV_NAME ": %s\n", __func__);
- + platform_driver_unregister(&semc_msm_irda);
- +}
- +
- +module_init(irda_init);
- +module_exit(irda_exit);
- +
- +MODULE_VERSION(DRV_VERSION);
- +MODULE_AUTHOR("Yoshida Manabu <[email protected]>");
- +MODULE_DESCRIPTION("SEMC MSM IrDA Driver");
- +MODULE_LICENSE("GPL");
- diff -ruN a/4.1.B.0.431//vendor/semc/hardware/irda/semc_msm_irda.h b/4.1.B.0.479//vendor/semc/hardware/irda/semc_msm_irda.h
- --- a/4.1.B.0.431//vendor/semc/hardware/irda/semc_msm_irda.h 1970-01-01 09:00:00.000000000 +0900
- +++ b/4.1.B.0.479//vendor/semc/hardware/irda/semc_msm_irda.h 2012-06-25 19:30:44.000000000 +0900
- @@ -0,0 +1,55 @@
- +/* drivers/serial/semc_irda/semc_msm_irda.h
- + *
- + * Copyright (C) 2011 Sony Ericsson Mobile Communications AB.
- + *
- + * Author: Manabu Yoshida <[email protected]>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2, as
- + * published by the Free Software Foundation; either version 2
- + * of the License, or (at your option) any later version.
- + */
- +
- +#ifndef _SEMC_MSM_IRDA_H_
- +#define _SEMC_MSM_IRDA_H_
- +
- +/* IrDA UART SW buffer settings */
- +#define IRUART_SW_TXBUF_SIZE UART_XMIT_SIZE
- +#define IRUART_SW_RXBUF_SIZE 512
- +#define IRUART_SW_RXRINGBUF_SIZE (IRUART_SW_TXBUF_SIZE*2)
- +
- +/* SEMC MSM IrDA driver - Platform data */
- +struct irda_platform_data {
- + int gpio_pow;
- + struct pm8058_gpio *gpio_pwcfg_low;
- + struct pm8058_gpio *gpio_pwcfg_hig;
- +
- + u32 paddr_uartdm;
- + int irq_uartdm;
- + int chan_uartdm_tx;
- + int crci_uartdm_tx;
- + int chan_uartdm_rx;
- + int crci_uartdm_rx;
- + char clk_str[12];
- + struct device *clk_dev;
- + int (*gpio_init)(void);
- +};
- +
- +struct irtxbuf_all {
- + int ptr;
- + int num;
- + u8 *buf;
- + dma_addr_t dmabase;
- +};
- +
- +struct irrxbuf_all {
- + /* read buffer */
- + int wp;
- + int rp;
- + u8 *ringbuf;
- + /* dma buffer */
- + u8 *buf;
- + dma_addr_t dmabase;
- +};
- +
- +#endif
- diff -ruN a/4.1.B.0.431//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/boot.c b/4.1.B.0.479//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/boot.c
- --- a/4.1.B.0.431//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/boot.c 2012-05-25 19:07:14.000000000 +0900
- +++ b/4.1.B.0.479//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/boot.c 2012-06-25 19:47:11.000000000 +0900
- @@ -2,6 +2,7 @@
- * This file is part of wl1271
- *
- * Copyright (C) 2008-2010 Nokia Corporation
- + * Copyright (C) 2012 Sony Mobile Communications AB
- *
- * Contact: Luciano Coelho <[email protected]>
- *
- @@ -472,6 +473,7 @@
- /* unmask required mbox events */
- wl->event_mask = BSS_LOSE_EVENT_ID |
- + REGAINED_BSS_EVENT_ID |
- SCAN_COMPLETE_EVENT_ID |
- PS_REPORT_EVENT_ID |
- DISCONNECT_EVENT_COMPLETE_ID |
- diff -ruN a/4.1.B.0.431//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/event.c b/4.1.B.0.479//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/event.c
- --- a/4.1.B.0.431//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/event.c 2012-06-10 23:35:50.000000000 +0900
- +++ b/4.1.B.0.479//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/event.c 2012-06-25 19:47:11.000000000 +0900
- @@ -129,8 +129,7 @@
- }
- static int wl1271_event_ps_report(struct wl1271 *wl,
- - struct event_mailbox *mbox,
- - bool *beacon_loss)
- + struct event_mailbox *mbox)
- {
- int ret = 0;
- u32 total_retries = wl->conf.conn.psm_entry_retries;
- @@ -157,7 +156,7 @@
- } else {
- wl1271_info("No ack to nullfunc from AP.");
- wl->psm_entry_retry = 0;
- - *beacon_loss = true;
- + ieee80211_connection_loss(wl->vif);
- }
- break;
- case EVENT_ENTER_POWER_SAVE_SUCCESS:
- @@ -255,7 +254,6 @@
- {
- int ret;
- u32 vector;
- - bool beacon_loss = false;
- bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
- bool disconnect_sta = false;
- unsigned long sta_bitmap = 0;
- @@ -301,26 +299,37 @@
- timeout = 500;
- ieee80211_set_dyn_ps_timeout(wl->vif, timeout);
- }
- -
- +
- /*
- - * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon
- - * filtering) is enabled. Without PSM, the stack will receive all
- - * beacons and can detect beacon loss by itself.
- - *
- - * As there's possibility that the driver disables PSM before receiving
- - * BSS_LOSE_EVENT, beacon loss has to be reported to the stack.
- - *
- + * We are HW_MONITOR device. On beacon loss - queue
- + * connection loss work. Cancel it on REGAINED event.
- */
- if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) {
- + int delay = wl->conf.conn.synch_fail_thold *
- + wl->conf.conn.bss_lose_timeout;
- wl1271_info("Beacon loss detected.");
- - /* indicate to the stack, that beacons have been lost */
- - beacon_loss = true;
- + /*
- + * if the work is already queued, it should take place. We
- + * don't want to delay the connection loss indication
- + * any more.
- + */
- + ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work,
- + msecs_to_jiffies(delay));
- + }
- +
- + if ((vector & REGAINED_BSS_EVENT_ID) && !is_ap) {
- + wl1271_info("Beacon regained.");
- + cancel_delayed_work(&wl->connection_loss_work);
- +
- + /* sanity check - we can't lose and gain the beacon together */
- + WARN(vector & BSS_LOSE_EVENT_ID,
- + "Concurrent beacon loss and gain from FW");
- }
- if ((vector & PS_REPORT_EVENT_ID) && !is_ap) {
- wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
- - ret = wl1271_event_ps_report(wl, mbox, &beacon_loss);
- + ret = wl1271_event_ps_report(wl, mbox);
- if (ret < 0)
- return ret;
- }
- @@ -409,9 +418,6 @@
- }
- }
- - if (wl->vif && beacon_loss)
- - ieee80211_connection_loss(wl->vif);
- -
- return 0;
- }
- diff -ruN a/4.1.B.0.431//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/main.c b/4.1.B.0.479//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/main.c
- --- a/4.1.B.0.431//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/main.c 2012-06-10 23:35:50.000000000 +0900
- +++ b/4.1.B.0.479//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/main.c 2012-06-25 19:47:11.000000000 +0900
- @@ -2346,6 +2346,7 @@
- cancel_delayed_work_sync(&wl->pspoll_work);
- cancel_work_sync(&wl->ap_start_work);
- cancel_delayed_work_sync(&wl->elp_work);
- + cancel_delayed_work_sync(&wl->connection_loss_work);
- mutex_lock(&wl->mutex);
- @@ -4223,6 +4224,13 @@
- wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x",
- (int)changed);
- + /*
- + * make sure to cancel pending disconnections if our association
- + * state changed
- + */
- + if (!is_ap && (changed & BSS_CHANGED_ASSOC))
- + cancel_delayed_work_sync(&wl->connection_loss_work);
- +
- mutex_lock(&wl->mutex);
- if (unlikely(wl->state == WL1271_STATE_OFF))
- @@ -5167,6 +5175,30 @@
- .read = wl1271_sysfs_read_fwlog,
- };
- +void wl1271_connection_loss_work(struct work_struct *work)
- +{
- + struct delayed_work *dwork;
- + struct wl1271 *wl;
- +
- + dwork = container_of(work, struct delayed_work, work);
- + wl = container_of(dwork, struct wl1271, connection_loss_work);
- +
- + wl1271_info("Connection loss work.");
- +
- + mutex_lock(&wl->mutex);
- +
- + if (unlikely(wl->state == WL1271_STATE_OFF))
- + goto out;
- +
- + if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
- + goto out;
- +
- + /* Call mac80211 connection loss */
- + ieee80211_connection_loss(wl->vif);
- +out:
- + mutex_unlock(&wl->mutex);
- +}
- +
- int wl1271_register_hw(struct wl1271 *wl)
- {
- int ret;
- @@ -5363,6 +5395,7 @@
- wl1271_rx_streaming_disable_work);
- INIT_WORK(&wl->ap_start_work,
- wl12xx_ap_start_work);
- + INIT_DELAYED_WORK(&wl->connection_loss_work, wl1271_connection_loss_work);
- wl->freezable_wq = create_freezable_workqueue("wl12xx_wq");
- if (!wl->freezable_wq) {
- diff -ruN a/4.1.B.0.431//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/wl12xx.h b/4.1.B.0.479//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/wl12xx.h
- --- a/4.1.B.0.431//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/wl12xx.h 2012-06-10 23:35:50.000000000 +0900
- +++ b/4.1.B.0.479//vendor/ti/wlan/compat-wireless-wl12xx/drivers/net/wireless/wl12xx/wl12xx.h 2012-06-25 19:47:11.000000000 +0900
- @@ -606,6 +606,9 @@
- /* Beaconing interval (needed for ad-hoc) */
- u32 beacon_int;
- + /* Connection loss work */
- + struct delayed_work connection_loss_work;
- +
- /* Default key (for WEP) */
- u32 default_key;
Advertisement
Add Comment
Please, Sign In to add comment